CodeinWP CodeinWP

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

16 Responses

  1. Mundi says:

    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.

    • Daniel Hug says:

      @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 says:

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

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

      [data-current] { }

  2. Scott Block says:

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

    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. Ben Bate says:

    Perfect, cheers!

  6. Jeremy says:

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

  7. subash says:

    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?

  8. Money says:

    It wont work with site layout or master page

  9. Doug Arnold says:

    10/04/2017

    Hello,
    I tried this and it didn’t work. What am I doing wrong please?
    Thank you.

    body.PageDesign a.PageDesign:link,
    body.PageProduction a.PageProduction:link,
    body.PageWeb a.PageWeb:link,
    body.PageLogoDesign a.PageLogoDesign:link,
    body.PageEndorsements a.PageEndorsements:link,
    body.PageResume a.PageResume:link,
    {
    font-weight: bold;
    }

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field and deep URLs are not allowed in the "Website" field. If you use keywords or deep URLs, your comment or URL will be removed. No foul language, please. Thank you for cooperating.

Markdown in use! Use `backticks` for inline code snippets and triple backticks at start and end for code blocks. You can also indent a code block four spaces. And no need to escape HTML, just type it correctly but make sure it's inside code delimeters (backticks or triple backticks).