Media Temple Hosting

Welcome to CSS Basics. More info on this section at the bottom of this post.

Current Page Link Styles

One of the most common things you’ll see on any website is a navigation bar that has a different set of CSS styles applied to the link that represents the current page the user is on. (Maybe I’ll actually get around to doing this on my own site!) There are a few ways you can do this with HTML and CSS, which I’ll outline here.

Using a Unique Link Class

Probably the most common and easiest way to do this is by simply applying a different class with appropriate styles on the current page link. So in your HTML you would see something like this:

<ul class="nav">
	<li><a href="index.html">Home</a></li>
	<li><a href="about.html">About</a></li>
	<li><a href="services.html">Services</a></li>
	<li><a href="products.html" class="current">Products</a></li>
	<li><a href="contact.html">Contact</a></li>
</ul>

The CSS would then require something like the following:

a:link, a:visited {
	color: blue;
}

a.current:link, a.current:visited {
	color: white;
	background-color: blue;
}

Now all links with a class of “current” will have white text on a blue background, while all other links will have just blue text.

The only thing you have to make sure of is that the location of the class gets changed depending on the page you’re on. For example, the HTML shown above would appear on the “Products” page, but on the “Contact” page the “current” class would be moved to the “Contact” link.

Adding a Class to the <body>

This next method is a lot messier, but is an option if you don’t mind more HTML. You can add a unique class to the <body> tag and then have a different class for each link. The body class would change depending on what page the user was viewing. So on the “About” page, your <body> tag would look like this:

<body class="about">

The HTML for your links would look like this:

<ul class="nav">
	<li><a href="index.html" class="home">Home</a></li>
	<li><a href="about.html" class="about">About</a></li>
	<li><a href="services.html" class="services">Services</a></li>
	<li><a href="products.html" class="products">Products</a></li>
	<li><a href="contact.html" class="contact">Contact</a></li>
</ul>

Then in your CSS you would have the following:

a:link, a:visited {
	color: blue;
}

body.home a.home:link,
body.about a.about:link,
body.services a.services:link,
body.products a.services:link,
body.contact a.contact:link {
	color: white;
	background-color: blue;
}

This includes a separate selector for each nav item. So although the different unique link classes will appear in the HTML on every page, the unique “current page” styles will only take effect on the page that has the matching <body> class.

Final Notes

A few things can be noted about the technique outlined here:

  • If you are using PHP (or some other back-end language), you can generate the classes dynamically based on the current page
  • Although I’m applying the unique classes to the link elements, you can use the <li> elements if you want
  • I’ve seen people use a class of “active” instead of the class of “current” that I’m using here; I think “current” (or something else other than “active”) is better because CSS already has a pseudo-class called :active that means something completely different, so that might be confusing for beginners
  • I suppose you could use the :nth-child() pseudo-class to target the current link by number in the list, but that seems a little convoluted and not very convenient or maintainable
  • If you want to do this on a WordPress site, this article covers that topic

Questions? Clarifications?

This post is not intended to be an exhaustive reference on this subject. It's meant to provide a simple CSS tip for beginners. If you have any questions or clarifications on anything I've said here, add them to the comments. If necessary, I'll continually improve this article to keep it up to date with the latest CSS standards and best practices.

This is the CSS Basics section of Impressive Webs. These posts do not appear in the main home page feed. You can subscribe via RSS or get an email notification whenever a new post is added.

13 Responses

  1. nice article. thanks for writing this up. you could also make use of CSS attribute Selectors like this…

    
    .home a[href="index.html"],
    .about a[href="about.html"],
    .services a[href="services.html"],
    .products a[href="products.html"],
    .contact a[href="contact.html"] {
        color: white;
        background-color: blue;
    }
    

    i’d be a little wary of using this on a really large app for fear of collisions with other links on the page with the same href. to mitigate, i’d more thoroughly qualify my selector by including the nav class like this…

    
    .about .nav a[href="about.html"]
    

    surprisingly, this stuff is compatible down to IE7. Chris Coyier has a really good run down here – http://css-tricks.com/attribute-selectors/

    cheers.

    • @Mundi I definitely agree with you here.

      Why?
      – Adding another unique class to each of the navigation links is superfluous, and hard to manage especially with dynamic content.
      – like you said, attribute selectors are supported in IE7+ (That’s plenty browser support for me)!

      This is how I would do the selector block:

      
      body.home nav a[href="index.html"],
      body.about nav a[href="about.html"],
      body.services nav a[href="services.html"],
      body.products nav a[href="products.html"],
      body.contact nav a[href="contact.html"] {
      	color: white;
      	background-color: blue;
      }

      …Or you could use it on the <html> element:

      
      html.home nav a[href="index.html"],
      html.about nav a[href="about.html"],
      html.services nav a[href="services.html"],
      html.products nav a[href="products.html"],
      html.contact nav a[href="contact.html"] {
      	color: white;
      	background-color: blue;
      }

      The reasons for using it on the <html> element would be the same reasons why IE conditional comments are put around the <html> element instead of the <body> element in Paul Irish’s browser-specific CSS solution:
      http://paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/

      • I agree that the html element is more appropriate than body element, but for this reason: The tagging applies to the whole page, hence the root element should carry that tag. (Keep in mind that at some point you might want to display content of the head element which is outside the body element.)

        And for the tagging, an ID is appropriate, not a class. You want to identify, not classify a page of your website. (Classes might be used for groups of pages, eg. product overwiew and product details pages belonging to a class “shop”, various checkout step pages belonging to a class “checkout”:
        <html id="product-overview" class="shop">
        and
        <html id="product-details" class="shop">
        and
        <html id="submit-order" class="checkout">
        respectively. Both ID and class can be used for styling.)

        • Joel:

          My understanding as to why class was used instead of id is because it allows for greater specificity when cascading. Class is given higher precedence than id, but there are other ways to attain specificity also. I agree that classes should be used to classify multiple elements and id is used to identify a specific element.

    • Steven Dufresne:

      I would be more comfortable using HTML data attributes than href attributes.

      [data-current] { }

  2. You can also do this easily on the client side with jquery, or if desired vanilla javascript.Kevin Leary has a nice jQuery tutorial- http://www.kevinleary.net/highlighting-the-current-page-with-php-jquery/ .

    You could argue that you shouldn’t be doing this on the client side, but it might be easier if you can’t access the server side code and you don’t want to add classes by hand for each page.

  3. David Hucklesby:

    My method of choice is to replace the “current page” link with some other element. That used to be <strong> until the meaning changed in HTML5 – I now use <em> to emphasize “you are here.” You could also use the neutral <b> element.

    You don’t need PHP to automate this – I have used good old Server-Side Includes to do it.

  4. I agree that “current” is a better class name than “active”. However, instead of a class you could use the @rel attribute <a rel="self"> in the markup and the attribute selector a[rel="self"] in the stylesheet.

    But that should not be necessary. “Never have a link that points to the current page,” says Jakob Nielsen.

    Following this advice, you’ll end up with markup like

    <nav>
      <ul>
        <li><a href="index.html">Home</a></li>  
        <li><a href="about.html">About</a></li>  
        <li><a href="services.html">Services</a></li>  
        <li>Products</li>  
        <li><a href="contact.html">Contact</a></li>  
      </ul>
    </nav>

    Then you can style the menu item (not link) for the current page using a selector like nav li and overwrite the styles for the other menu items using nav a (or nav li a).

    Or you keep the a element for the current page, but without a @href attribute:

    <nav>
      <ul>
        <li><a href="index.html">Home</a></li>  
        <li><a href="about.html">About</a></li>  
        <li><a href="services.html">Services</a></li>  
        <li><a>Products</a></li>  
        <li><a href="contact.html">Contact</a></li>  
      </ul>
    </nav>

    This allows to discriminate the menu item for the current page from the others using selectors like nav a vs. nav a[href].

  5. Thanks for writing the blog post.
    I realised it’s an older post but your taking the time to share your ideas helped.

  6. subash:

    what if i am inside the dreamweaver template? I can only edit in template pages but not in child pages. So, i cannot add class in each child pages?

  7. Money:

    It wont work with site layout or master page

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field. If you use keywords, your comment will be deleted, or your name will be replaced with the alias from your email address. No foul language, please. Thank you for cooperating.

Instructions for code snippets: Wrap inline code in <code> tags; wrap blocks of code in <pre> and <code> tags. When you want your HTML to display on the page in a code snippet inside of <code> tags, make sure you use &lt; and &gt; instead of < and >, otherwise your code will be eaten by pink unicorns.