CSSnewbie

About CSSnewbie

Our mission is to help the beginning to intermediate web designer master the subtleties of CSS by offering CSS tutorials, tips, and techniques.

Recent Article

Intelligent Navigation Bars with JavaScript and CSS

Posted on 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.

Responses

On 2/20/2008 at 9:38am, Chris Coyier said,

That’s awful slick, nice work Rob. Really keeps the markup clean without having to add classes inside the menu for no real semantic reason.

On 2/20/2008 at 12:30pm, Wolf said,

li class=”selected” is as semantic as gets, unless you have a crafty templating system that makes the anchor a span if you are on that page.

Not giving any indication of where people are, even just in source code is absolutely worse than adding an “”unneeded”" class.

On 2/20/2008 at 2:16pm, Chris Coyier said,

@Wolf: But navigation code is generally dynamically added to individual pages so adding class=”selected”, while arguably semantic, is usually not an option.

On 2/20/2008 at 2:57pm, David Hucklesby said,

Neat idea.

Another possibility is to change the A tag to a B or STRONG. That automatically gets rid of the pointer-type cursor, and indicates current location even when styles are not applied– for Netscape 4 users, for example.

On 2/20/2008 at 8:48pm, sklar said,

Would manually specifying a tag have an advantage over this solution if the user had js disabled?

On 2/20/2008 at 11:04pm, Rob Glazebrook said,

Great conversation, all. :)

@David: That would work very well, assuming your tab or whatever was specific. But if, for example, you were deep in the “archive” directory, it could be useful to still have the “archive” tab act as a link, to take the user to the root of the archive. It depends a lot on how your directories and tabs are structured.

@Sklar: Specifying a class or ID in the navigation or body would mean that it would work even with JavaScript disabled. However, that also means you have to add an extra class or ID to every page in your site. There are benefits to either approach, really. :)

On 2/22/2008 at 12:50pm, Pages tagged "javascript" said,

[…] tagged javascriptOwn a Wordpress blog? Make monetization easier with the WP Affiliate Pro plugin. Intelligent Navigation Bars with JavaScript and CS… saved by 3 others     ilovesasuke401 bookmarked on 02/22/08 | […]

On 2/22/2008 at 5:08pm, Tom K. said,

Every site I run into this same problem, and when i 1st started designing I was like,”wait there isn’t something that can detect what page you are on… I have to update the code for every page”

What would be nice, is if it could sniff what folder the doc is in. So any html file in this folder will get this header. Anyone ever heard of this?

Good Read!

On 2/23/2008 at 9:09am, Fatih Hayrioğlu’nun not defteri » 23 Şubat 2008 web’den seçme haberler said,

[…] CSS menü javascript yardımı ile aktif tab uygulaması. Bağlantı […]

On 2/25/2008 at 1:47pm, Nate22 said,

I don’t understand. I copied and pasted your Source code into an html file, opened it up and it doesn’t work.

Do the links have to have “?links”

Is this entirely dependent on php or something?

On 2/25/2008 at 1:53pm, Rob Glazebrook said,

Hi Nate,

No PHP required here. You should just change the anchor tags in the unordered list to wherever you want them to go. I added “?link” to them to make them act like different pages while really existing on the same page. In practice, they’d all go to ~real~ different pages.

You can see from the example page how the code all works together… just make sure your Javascript is between <script> tags, and set your links to pages that actually exist.

Hope that helps!

On 2/25/2008 at 1:53pm, Nate22 said,

I’m talking about this source code:
http://www.cssnewbie.com/example/intelligent-navigation/?about

I copied and pasted it to an HTML document and saved it to my desktop. When I opened it in the browser, the intelligent navigation doesn’t work.

So, is it php dependent or something?
I’m used to links that look like “< a href=”www.whatever.com/link.htm” … NOT “.

Hope that was clear. I can’t think of any other way to explain.

On 2/25/2008 at 1:54pm, Nate22 said,

Erg. I mean I’m not familiar with links that look like this:

a href =”?about”

Is that ?-styled link php or something?

If so, maybe that’s why it doesn’t work.

On 2/25/2008 at 1:55pm, Nate22 said,

Thanks, Rob. Huh, I wonder why it didn’t work. Will try again. Thanks! Great breadcrumb solution, btw. Been driving myself crazy with others!

On 2/25/2008 at 1:57pm, Nate22 said,

haha, it works great. i’m retarded.

On 2/26/2008 at 2:30pm, CSS-FAQ » Blog Archive » Glazebrook proposes ways on how to create intelligent navigation bars said,

[…] on the first tab – for instance, linking to “/blog/index.php” instead.” You can go to http://www.cssnewbie.com/navigation/intelligent-navigation/ for some cool stuff about this and other relevant things on […]

On 2/29/2008 at 7:06am, Sean Nieuwoudt said,

great work!

On 3/3/2008 at 3:03am, ) design collected ( :: links for 2008-03-03 said,

[…] Intelligent Navigation Bars with JavaScript and CSS - CSSnewbie A navigation bar that 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. (tags: css javascript active-navigation navigation) […]

On 3/22/2008 at 2:00pm, TFD said,

Great. I just love simple but powerful solutions like this. Just like the suckerfish method:

http://alistapart.com/articles/dropdowns
http://www.htmldog.com/articles/suckerfish/dropdowns/

Thanks for posting Rob.

TFD

On 4/1/2008 at 3:17pm, David Sarnowski said,

Is it possible to see a full example page with this active. i cannot see where to place the javascripts.

Thank you,

Dave

On 4/2/2008 at 6:23am, David Sarnowski said,

When I try and add this javascript to my Blogger template, I get the following error:

Your template could not be parsed as it is not well-formed. Please make sure that all XML elements are closed properly.
XML error message: Element type “aObj.length” must be followed by either attribute specifications, “>” or “/>”.

any thoughts?

Dave

On 4/2/2008 at 9:16am, Rob Glazebrook said,

Hi David,

You can seea a working example of the script here.

If you look at the source of the page, you’ll see where you need to put the JavaScript: between a <script> and and </script> tag in the head of your page.

I hope this helps!
-Rob

On 4/2/2008 at 4:25pm, robglazebrook.com » Blog Archive » CSSnewbie - 2 Months Update said,

[…] I was never able to get quite back up to where I was before. The StumbleUpon people really loved my “Intelligent Navigation” article, and I’ve gotten a lot of feedback on it. There were a few other peaks in there, topping […]

On 4/10/2008 at 6:17am, takeru said,

..but what if there’s subnavigation?

On 4/10/2008 at 6:17am, takeru said,

..but what if there are subnavi?

On 4/24/2008 at 7:43pm, Coxsone said,

I am having the same problem with subnavigation as takeru. I have a Main Nav and a Sub Nav both using this method on the same page.

If I have a Main Nav item “Products”, how would I have this remain “setActive” for muiltiple pages on Sub Nav pages such as “Product1.php”, “Product2.php”, “Product3.php”, etc.

These multiple .php pages are “Products” pages require “Products” selected ont the Main Nav. How can I do this?

Leave a Reply

Do More