1. Web Design
  2. Site Elements

Tabbed Navigation: Adding CSS Classes Dynamically


I love tabs, I have done for as long as they've been around! Let's see if we can harness some javascript and CSS3 power to build a great tabbed navigation. We're going to use javascript to auto-detect which tab the visitor is currently on and even make this compatible as far back as IE6. Long live CSS3pie!

Step 1: HTML <head>

The easy part...

As we want our page to be compatible with IE 6-8, we use the "HTML - 4.01 Transitional" doctype. Let's have a look at the template:

Dead links are better than no links!

Your web editor should have this template, otherwise copy this to index.php in your main folder.

We have three external files which we'll create or add later. Like my great-grandfather always said: dead links are better than no links. will be linked from the css file, so we only need to link the javascript and the css file.

Step 2: HTML <body>

This is the plan:

The container, header and the content are div layers. The container contains everything and its function is to prevent the content from shrinking more than 800px. The header is the tab system and the content speaks for itself. The tab system consists of an unordered list which we'll align horizontally. Each list item contains a link to another page. With this in mind it isn't hard to come up with the markup:

This is what we have so far:

It has all its functionality, but clients are never going to be happy with such a simple design. Good news for you..

Step 3: CSS CSS2 Only

So we need some basic styling. Create tabs.css and place it in the same folder as index.php

We start with styling the body and the container:

Neither element has anything special, except for the margin. The container is easy: if margin-left and margin-right of an element (with a defined width) are set to auto, every browser will try to center that element.

The negative horizontal margin of the body isn't that hard either. The width of the container is 800px for compatibility with old screens, but we are going to add rounded corners to them, each with a radius of 12px. This makes the corners shrink, so we add a padding of 12px to the container.

Step 4: Result Thus Far

Check what you've built so far. If the screen is too small (below 800px), you'll notice the rounded borders at the left disappear. They are unnecessary so our negative margin tucks them nicely out of sight.

To keep things readable, we should also change the background color of the content and the tabs.

Step 5: JavaScript Domready

Before we continue styling the tabs, we want to add one of the most important (and brilliant, though I say it myself) parts of this: the selected tab should be white. We aren't going to change the tabs on every page. We let javascript do the dirty work.

This code runs the function init (which doesn't exist yet) when the content is loaded. If you only use window.onload, the javascript will execute after all external files (like images, stylesheets) are loaded. This will result in a naked website for a few seconds, without the cover of javascript. And yes, your host will ban you for publishing adult content...

Step 6: JavaScript init()

Let's create that init function. This function detects which tab you're currently viewing, removes its hyperlink (the visitor is there already) and assigns a class.

Step 7: JavaScript init() Breakdown

Allow me break it down for you.

This is a shorthand for the long document.getElementById. It was useless this time, because I only used it once. But using it is a good habit to get into.

This starts a loop through all anchor tags in the header.

This is the most important part. The href attribute of an anchor returns the absolute path. If the href attribute is the same as the current page the visitor is on, then that's the current tab. But if the visitor is in the home folder, he actually is on the home page.

This anchor doesn't need a href attribute anymore. The parent node is the list item. We assigned the selected class to this item, which doesn't exist yet. Remember what my great-grandfather said.

If the script finds the current tab, it can stop searching.

This is what we have:

As you can see, the first link has changed to normal text.

Step 8: CSS Header and Content

OK, we've done the boring part. I've split the final styling in two parts: positioning and coloring.

We need to center the header and set its width to 600px. We can use the same trick as we used with the container. The content layer is as big as the container (coincidence?), so no need to center it.

If you don't believe we're making progress:

Step 9: CSS Tab list

I'm sorry you had to wait this long for this part, but we made the necessary preparations and we are ready to roll.

The tabs should be aligned horizontally and have the same width. The anchor tag should cover the whole tab.

If you've more or fewer tabs than 3, make sure you don't forget to change the width of the list items!

By default, the display of a list item is set to 'list-item' which is very similar to 'block', except for the marker. Block elements act like paragraphs and divs; they try to stay off the same line. Anchor tags and most markup tags (strong, em) are inline elements. They don't force a line break, but we can't specify their width.

But there's a third display type: inline-block. Inline-block allows you to change the width, but it doesn't force the line break. span elements are displayed as an inline-block by default.

That's exactly what we're looking for. But there's one drawback. IE 6 doesn't support inline-block. zoom: 1; and *display: inline; take care of that. Only IE 6 and lower read rules starting with an asterisk.

No padding and margin for the ul and list items. Our 'Home' tab aligns perfectly at the left side and the last tab aligns perfectly at the right.

This looks more like it...

Step 10: CSS Fancy Stuff

We made a clean design. It's fine, but ze dezign zjould havé impacte, like an italian client once said. And I couldn't have said it better myself.

First you have to grab from here. IE 6, 7 and 8 don't support CSS 3, this is a fallback. Drop it in the public root folder of your site.

Step 11: CSS Gradients are Great

Instead of styling every list item, we give the whole list one big gradient and change the selected one back to white. Every browser type has a different prefix for gradients and CSS3pie expects the -pie- prefix.

The background-color can stay. It's a fallback for browsers which support neither CSS 3 nor

Step 12: CSS Round Those Corners!

Three elements need to be rounded: the whole navigation bar, the selected tab and the content. And again, every browser type requires a prefix, but pie doesn't this time.

We are almost done...

Step 13: Dark Theme

First we change the color of the text to dark blue, remove the underline and punish it with early hair loss:

The color difference is pretty big, but the text doesn't pop out. Stroking the text would be the solution. Safari and Chrome support text-stroke, but other browsers don't. However, all modern browsers + CSS3pie support text-shadow.

Step 14: The Content Files





Firstly, a final fiddle.

Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.