June 13th, 2007 - by Paul OB

This article will show you how to highlight the current page’s link in a navigation menu using only CSS, no scripting. For example, if you have a navigation menu made up of Home, About, Contact and Products links and our viewer is currently viewing the About page then the link will be highlighted or in some way indicate that they are viewing that page.

The usual way to go about doing this is to add a class to the link that identifies the current page. However, the class would need to be moved to the relevant link on each page so that only the link that refers to the current page is affected. While this method works just fine it means that the menu cannot be part of an include because it is different on each page due to the current class changing position on each page to reflect the current page. In this brief article I will show you how to automate this process (to a degree) that will allow the menu to be part of an include.

The first thing we need is to construct our menu — since a menu is really just a list of links we will use a list to accomplish this in the most semantic way.

  1. <ul id="nav">
  2. <li class="one"><a href="index.htm">Item 1</a></li>
  3. <li class="two"><a href="page2.htm">Item 2</a></li>
  4. <li class="three"><a href="page3.htm">Item 3</a></li>
  5. <li class="four"><a href="page4.htm">Item 4</a></li>
  6. <li class="five"><a href="page5.htm">Item 5</a></li>
  7. <li class="six"><a href="page6.htm">Item 6</a></li>
  8. <li class="seven"><a href="page7.htm">Item 7</a></li>
  9. </ul>

I have chosen to use class=”one”, class=”two” etc. to make it easier to follow along in this demonstration (don’t be tempted to use class=”1″ as class names or id’s cannot begin with a digit.)

Now that we have a means of addressing each list item due to the class identifier we placed there we will add a class to the body tag. Once we have added the class to the body then it is a simple matter of using that body class combined with the list class to target our current page.

For the home page the CSS would be:

  1. body.section1 #nav li.one {background:#ffffcc;}

What we are saying here is that only on pages that have a body class of section1 and a link with a class of one have its background coloured. We simply repeat that process for all the links in the menu and the resulting CSS looks like this:

  1. body.section1 #nav li.one,
  2. body.section2 #nav li.two,
  3. body.section3 #nav li.three,
  4. body.section4 #nav li.four,
  5. body.section5 #nav li.five,
  6. body.section6 #nav li.six,
  7. body.section7 #nav li.seven {background:#ffffcc;}

The only extra task is that on each of your HTML pages you must make sure that the correct class is in place in the body tag for this to work. For example, on page2.htm the body tag should like this:

  1. <body class="section2">

Once you have done that then the correct page will automatically be highlighted when the user lands there. Here is a full demonstration of the above technique where you can navigate to each page to test it out.

Drawbacks

The main drawback is that there are the extra classes in the HTML needed to accomplish this; otherwise it is a useful technique. You could also do this with server-side or client-side scripting, but that wasn’t the purpose of this demonstration.

I should also point out a couple of accessibility issues with the above approach. The first is that it is generally considered bad practice to have the current page still be an active link. However, in some situations this may be unavoidable.

The second accessibility issue is that colour alone is not enough to identify the current item as that would discriminate against those with poor sight or colour blindness, so you should have suitable alternatives built into your accessibility strategy.

That should do it – you have now learned a 100% CSS solution to highlighting the current link in a navigation menu for the page you are on. Until next time – happy coding!

44 Responses to “CSS Current Page Indicator”

1 Guilherme Zühlke O'Connor

This is a very nice trick.

Well, not really a trick, I think is an elegant solution to the problem and really makes sense, semantically speaking.

The CSS selector roughly translates to something like “The the link tho *this* page should be styled like the following.

I don’t think putting classes in the body element is, by any means, a drawback, it just makes sense.

2 John

Another drawback would be that if you have a lot of links, the added HTML/CSS could soon get unweildy so it would depend on the situation.

3 css menus

not so sure that is any different than assigning which nav item is “current” in the menu itself. You’re just using the body class to do the same thing. If the bosy class is already being used for something then I guess it makes sense, but just using the body class primarily to specify the page you are on for the nav menu isn’t any different then bringing it down into the menu itself.

4 Dan Schulz

I prefer using IDs myself, but then again “to each their own” as they say.

5 Paul OB

Hi, Sorry for the late reply But I’ve been away.

The reason to move the current class to the body is mainly for when using menus as “includes” and that means the menu must be the same on all pages without change.

I always class my body tags on each page anyway (or use ID’s) as it is very useful to be able to identify pages either individually or by groups and in my opinion should be done as a matter of course.

This will also allow you to change things such as background images on those pages all by using the same mechanism as described in the article without having to touch the html again.

@Dan – Yes id’s can be used for this also but I didn’t want to confuse beginners who may already have ID’s in their body tags and as we all know you can’t have two ids on the same tag but you can have multiple classes on the same tag :).

6 Best of May/June 2007

[…] CSS Current Page Indicator This article will show you how to highlight the current page’s link in a navigation menu using only CSS, no scripting. For example, if you have a navigation menu made up of Home, About, Contact and Products links and our viewer is currently viewing the About page then the link will be highlighted or in some way indicate that they are viewing that page. […]

7 Christian

Even when using menus as “includes” you can assign an id to the current menuitem (php?).

If you have a small menu with only few items, this is a solution you might consider even though it’s “out of the ordinary”, but when dealing with large menus – I wouldn’t use it.

But then again – everybody has different preferences.

8 Paul OB

HI Christian,

Thanks for your comments.

I’m not sure what you mean by “out of the ordinary” as this is a well established technique and extremely useful and one I have used literally hundreds of times to good effect on many, many sites in real situations.

You are right in that the more menu items you have then the more css you will need to target each item but if you have loads of menu items then I suggest that you are doing something wrong as you should not overload your visitor with millions of links in your main menu.

Of course this can be done server-side but as this column is about CSS and not PHP then the article is about creating CSS based techniques 🙂 If you are capable of coding in PHP then a server-side solution is probably a more viable method of accomplishing this.

The main point off the article is to show how CSS can be manipulated and although you may not wish to use the technique in your menu it can be applied to any element for similar effects.

9 Yoram

Exactly what I was looking for. Great, elegant solution. I like it!

10 dr john

“… it is generally considered bad practice to have the current page still be an active link.”

Stu at cssplay gives the illusion that a link is not clickable by playing with the cursor style in some of his overlapping tabbed menus
http://www.cssplay.co.uk/menus/
http://www.cssplay.co.uk/menus/overlap.html

Perhaps that idea could be included here too.

11 Paul OB

Hi Dr John,

Yes you could set the active link to have cursor:default so that it looks less like a link and may stop people clicking 🙂

12 graphicsguy

Does anyone know how to make the current page issue work when using expanding tabs that use 2 gifs.

Ex. I have gifs that look like rounded tabs:

#masthead ul li {
float: left;
background: url(../images/tab_right.gif) no-repeat top right;
display: inline;
}
#masthead li a {
float: left;
display: block;
padding: 0 6px;
line-height: 2.5em;
background: url(../images/tab_left.gif) no-repeat top left;
text-decoration: none;
color: black;
}

Than the background and text color change during hovering:

#masthead ul li:hover {
background: url(../images/tab_right_hover.gif) no-repeat top right;
}
#masthead ul li a:hover {
color: #00f;
background: url(../images/tab_left_hover.gif) no-repeat top left;
}

Now I’d like to have the current page have the body color with the tabs outlined in gray. I have created the gifs for it but can not get them to both display when on the current page. It seens I have tried every combination imaginable.
Does anyone know how to do this?

13 Paul OB

Hi graphicsguy,

Assuming you have set the id in the body correctly and you have added classes to each of the menu items then you would do something like this:

#masthead ul li:hover,
#page1 #masthead ul li.page1 {
background: url(../images/tab_right_hover.gif) no-repeat top right;
}
#masthead ul li a:hover,
#page1 #masthead ul li.page1 a {
color: #00f;
background: url(../images/tab_left_hover.gif) no-repeat top left;
}

Hope that was what you meant.

14 Paul OB

In answer to Dr Johns query in post 10 I went one better than Stu’s method and created a current link that could not be clicked 🙂

http://www.pmob.co.uk/temp2/page1.htm

15 Navigate-This

[…] ID. This will allow for the menu to be used as an include and is the same technique used in the “current page indicator” […]

16 fibercement

I don’t think putting classes in the body element is, by any means, a drawback, it just makes sense.

17 dıs cephe

thanks paul..

18 bayanlar

There are working fine now! Thanks.

19 Matthew

Thanks so much for this tip. I’m a CSS noob and I was able to get this working on my new site.

20 graphicsguy

More great advice, thank you. I’m anxious to try this as soon as I get home. I’ll leave feedback if I’m able to make it work for me.

21 Jen

Thanks for this tutorial. I was looking for a good CSS solution and this works great.

22 Celik Konstruksiyon

Thanks you for a lot dude!

23 Davin

I think a slightly better option and one I have done on my site so that one does not have to remember what to put into the body tag is to on page load loop through the anchors in the nav and compare them to the current page. If one matches then put int a class that highlights that item and remove the anchor tag. I did this pretty easily with jQuery.

24 Paul OB

Hi Davin,

Yes that’s fine (as long as javascript is turned on of course) or better still do it serverside with php 🙂

These are CSS articles so we stick to CSS techniques but of course it can be done serverside with something like php or clientside with js.

25 Jerry

Great stuff Paul. I always love ‘pure’ CSS solutions, and this technique has lots of real world applications. Great mod to get the ‘current’ link disabled too!

26 Jules

thanks, I always wondered how this was done, I’ve used this in my site and bookmarked it 🙂

theres a typo in the css after li.one there should be a comma – had me stumped for a while

27 Paul OB

Thanks for spotting the typo Jules.

28 HM Mohsan Raza

Active page indicator

I mean when any page active than hover link be still on current page

29 Charles Ofoefule

In a situation where you are you using one function (e.g a PHP funcion) to display the navigation bar for all the web pages. (NB that function contains the body tag) This solution would not apply.
In such a situation, what are the options available??

30 Paul OB

@Charles: You would need to dynamically add the class to the body tag Via php preferably.

http://www.alistapart.com/articles/keepingcurrent/

If you are using PHP anyway then there are quite a number of php routines about that could grab the current url and adjust the class accordingly.

In my example you could add the class to the html element instead although it’s not really allowed by the specs but is unlikely to do harm.

31 Guest

Great tutorial. I spent about 2 hours searching for this solution and finally I found this tutorial.

Thanks a lot.

32 Rory

Hey Paul,

really impressed with all your work, helping the CSS noobs!

I’m trying to integrate this into a website I’m currently working on, but am a little confused as to where I add the

” body.section1 #nav li.one {background:#ffffcc;} ”

I plan to use your CSS code to change the colour of the text on the page you are on. So i’m guessing instead of:

{background:#ffffcc;}

I would have something like:

{color:#630;}

would really appreciate your help.

thanks,

Rory

33 Paul OB

Hi Rory,

If you want to change the text color instead of the background color thewn just change the rule fr each.

body.section1 #nav li.one {color:red}
body.section2 #nav li.two {color:blue}

etc…

If on the other hand you meant you wanted to change the text on the whole page then you would need to address the elements that are giving the colour to the page.

If you have just set the color on the body element then you can just set up classes to change it for each page as required.

Just add a different class to the body tag on each page and then address the style using that class.

e.g.

body.page1 {color:red}
body.page2 {color:blue}

etc….

Then in each page make sure you have added the correct class to the opening body tag as required.

If on the other hand you have specifically added colours to different elements then you will need to target those elements via the body class.

e.g.

body.pag1 h1 {color:red}
etc…

Hope that covers what you wanted.

34 erinn

Hello, I would like to apply this technique to my page – however my links are triggering an image swap event which occurs within the same html page. I would like the link corresponding with the current image to be highlighted. Is this possible using the code you suggested above?
thank you.

35 Paul OB

Hi Erinn,

It depends on what you mean by image swap. If you are using javascript then css can’t affect that but if you are simply swapping the nav menu items on hover then you should be able to target those in the same way as the background is changing.

If you meant something more complicated I’d need to see the page and check first 🙂

36 James

So, I tried doing this and I don’t quite get it.

I copied the code above, swapped out my variables, but it didn’t work.

Instead of class’ I am using ID’s.

That’s it. Should work, right? What’s up?

37 Sarah

Hello,

Your solution to the active link css seems to be just the thing I need, but I am having trouble customising it to work with my nav menu.

1. I’m creating a Dreamweaver template with the nav menu set up in it;

2. In the css file I’ve got each of the menuitems each with a background image: #menutop li.buttonHome a{background-image…..}

3. there is also a hover with a different background image: #menutop li.buttonHome a:hover {background-image….}

4. This all works so far just fine. In the Template I’ve specified editable attributes for:
– the class of each a href on the menu buttons

– and the class of the body tag.

What I would like to do is set the menu up so that on the currently viewed page, a third background image, namely the one with a different colour, etc. displays instead of the default link image.

How can I do this with the code you have provided here? I’ve tried changing the body class and menu button class via the “Modify Template Properties” in Dreamweaver but it’s not working…

Along with this, I would like to have the active link class override the a:hover function, as well as disable the a href of the button corresponding to the currently viewed page.

Can you help? This would all be simple enough I think, if I wasn’t trying to get it all into the one template. I’m just trying to avoid having to make changes to the nav menu on every single page of my site…

Thanks!

38 Paul OB

Hi Sarah,

There should be no problem in having a third type of image for the current page as you would just adjust the code accordingly.

e.g. roughly:

#nav li.one a {
background:yellow;/* normal*/
}
#nav li.one a:hover {
background:blue;/* hover*/
}
body.section1 #nav li.one a,
body.section1 #nav li.one a:hover{
background:red;/* current*/
}

If you don’t want the current nav clickable and you don’t want to change the link to a span on the current page then you could use the technique from this example instead.

http://www.pmob.co.uk/temp2/page1.htm

A span is absolutely placed over the link (when it is current) so that you can’t click it. When it is not current the span does nothing.

It’s too hard to provide support through a blog post so if you want detailed help then post in the Sitepount CSS forums (http://www.sitepoint.com/forums/forumdisplay.php?s=&daysprune=&f=53) where its easier to post code, links and attachments.

39 mia

Thank you for this.
It works in IE 7 & 8 but not in Firefox.
Help

40 s.lourdoss

but is it is possible showing current thumbnail indicator in a single page with more number thumnail

41 Paul OB

@Mia: It should work everywhere. You must have an error in your code. You’ll need to provide more info if you want help.

42 Paul OB

@s.lourdoss: We’d need to see exactly what you are trying to do to answer that I’m afraid.

43 EJ Note

Great article – even given it is 4 years old. I just ran across a site that needed a similar solution and with the new CSS3 child selectors this can be done through pseudo-classes. It eliminates the need for adding classes to each list item.

body.section1 #nav li:nth-child(1), body.section2 #nav li:nth-child(2),… {background:#ffffcc;}

44 Jenny

A helpful article.

One question though.

When I set the css to highlight the current menu, it works just fine. But when I have a drop-down menu, the css hightlights the entire drop down menu (meaning every item so the entire menu is that highlighted color.

I only want the menu to be highlighted and not the entire block. Can I ask for your help? Thanks in advance!

mulberry sale spyder womens jacket cheap new balance 574 mulberry outlet cheap new balance 574 arcteryx outlet mulberry sale spyder womens jacket mulberry sale spyder womens jacket mulberry outlet mulberry outlet new balance 574

Popular Articles

Top 10 Commentators


Subscribe to this feed! Subscribe by Email!

Random Bits Podcast

You need to download the Flash player from Adobe

Blogs Worth Reading