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.

HTML:
  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:

CSS:
  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:

CSS:
  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:

HTML:
  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!

17 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..

Share your thoughts...

WordPress Plugins

Blog Categories

Meta

Add this blog to my Technorati Favorites!

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