Intelligent Navigation Bars with JavaScript and CSS

Published February 20, 2008 by Rob Glazebrook.

Arnold as the Terminator

I’ve developed a trick over the years that I’ve used on a number of websites now for making my sites’ navigation bars “intelligent” or “self-aware.” By that, I mean that the navigation bar automatically knows which tab/button/whatever should be considered the currently active link, without having to manually specify a class or ID on either the body tag or on the links themselves. And since I’ve found it so useful, I thought I should share it with you, even though it does involve a smidgen of JavaScript.

I start with an unordered list that looks something like this:

<ul id="nav">
	<li><a href="/about/">About Us</a></li>
	<li><a href="/contact/">Contact Us</a></li>
	<li><a href="/archives/">Our Archives</a></li>
	<li><a href="/free/">Free Stuff</a></li>
</ul>

Then I turn the unordered list into a navigation bar, using the technique I described in my last article. I won’t delve into those details here, for the sake of brevity and my fierce, fierce (fierce!) hatred of repetition, but you might want to read the prior post first if you missed it. The navigation bar gives me tabs that expand nicely for different text sizes and respond by growing and changing color when people hover over them.

But what if you want to somehow indicate to your users which page or section of the site they’re currently visiting? For that, I use the following JavaScript magic:

function setActive() {
  aObj = document.getElementById('nav').getElementsByTagName('a');
  for(i=0;i<aObj.length;i++) { 
    if(document.location.href.indexOf(aObj[i].href)>=0) {
      aObj[i].className='active';
    }
  }
}

This tiny little function does four things:

  1. Finds all of the anchor tags (via getElementsByTagName) inside of the element with the “nav” id (getElementById) – our unordered list, in this case.
  2. Cycles through every anchor tag that we’ve found (our “for” loop).
  3. Compares the “href” of the anchor tag with the page we’re currently on (document.location, which is the URL that shows up in the bar at the top of your browser) to see if the href is contained therein.
  4. If the href is a match for the page we’re on, it sets a class of “active” on the anchor tag (className=’active’).

Then we have to make sure to run the setActive script when we load the page, so that our tab gets set as soon as the page is loaded. I accomplish that with this line of JavaScript somewhere below my setActive function within the same file:

window.onload = setActive;

After that comes the CSS. Because we’ve used our JavaScript to set a class of “active” on our tab, all we need to do is style the active class. I usually do something fairly simple like the code below, which make the tab drop down from the top, applies a background color, and gives it a dark border on all sides but the top:

ul#nav li a.active {
	padding-top: 15px;
	background-color: #075a97;
	border: 1px solid #333;
	border-top: none; 
}

And voila! Your navigation bar suddenly knows and indicates exactly where you are, without having to remember to specify any extra IDs on the body tag or navigation links. You can see it in action here.

As a caveat, this technique assumes that you’re not linking to a lot of commonly-nested directories in your navigation. For instance, if you have one tab going to “/blog/” and another to “/blog/archive/”, then both tabs will inherit the “active” class when you’re in the archive directory (because /blog/ is part of /blog/archive/). One way to get around this limitation would be to be more specific on the first tab – for instance, linking to “/blog/index.php” instead.

79 Responses

  1. Mike Muller (reply)

    Hello, This is great.

    Do you know how I can get the class to be applied to the li instead of the a.
    So it would be (li class=”active”)(a href=”/about/”)About Us(/a)(/li)
    Any help would be greatly appreciated

  2. condensermike (reply)

    I am having the same issue as Borxu, it will not work in Safari. Any ideas why?

    Thanks for your code and your help!

  3. tattoo removal cost (reply)

    Wow, superb blog layout! How long have you been blogging for? you make blogging look easy. The overall look of your web site is magnificent, as well as the content!. Thanks For Your article about Intelligent Navigation Bars with JavaScript and CSS .

  4. PG (reply)

    Works perfectly in IE, but the active page part seems not to be working in firefox. Is there any solution to this problem?

    Many thank

  5. cbnl (reply)

    The active page bit works fine in .html files but doesn’t in .php files.

    Is there any fix/workaround available?

  6. Carlos G. (reply)

    I’ve just started learning web design, and this is cool! :D
    The only problem i’m having right now is that it works with my internet browsers but not in dreamweaver. It’s weird… Also, do i need to put the javascript into every html document? Anywho, thanks a lot! :)

  7. Pingback: Using JavaScript to Style Active Navigation Elements

  8. venkatesh (reply)

    Thanks a lot bro
    I’ve been searching for this from last 2days, finally found you and it working great. Thank you very much bro

  9. Pingback: Easiest way to class “current page” nav element? - PHP Solutions - Developers Q & A

    1. Rob Glazebrook (Author) (reply)

      Hi Sarang, click the “You can see it in action here” link in the second-to-last-paragraph. I agree I probably need a more consistent way to link to demos.

  10. Jordan (reply)

    This code works great, however I am still having trouble making my “home” tab load as active. All of the tabs highlight once I click on them, but when I first load the project, nothing will show as active even though “home” should. Can you help?

  11. Salimon (reply)

    You’re so interesting! I don’t think I’ve truly read something like
    this before. So wonderful to find someone with some unique thoughts on this topic.
    Really.. thank you for starting this up. This web site is one thing that’s needed on the internet, someone with a bit of originality!

  12. Sebastian (reply)

    Is there a change to get this working for frameset or iframe?

    Therefor the line if(document.location.href.indexOf(aObj[i].href)>=0)

    need a change to the src of the frame. But I don’t know kow.

  13. newcaredentist (reply)

    Hi! Thank you very much for this amazing code! I have an issue, though: I added the code to TWO vertical navigation bars, one in the middle-left area and a second one in the bottom-left area of my blog:
    http://newcaredentist.blogspot.gr/
    It works correctly only in one of them. I mean that it does not mark the active state in both of the navigation bars simultaneously but only in one of them – to be more specific, to the one that is added last. Can you give me any suggestions of how to resolve this issue? Thank you in advance!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>