CSS for Navigation Designs

CSS Tabs: Imageless

Imageless tabs produce a very simple, fairly elegant visual appearance, for example:

The following method uses this XHTML code:

	<div id="nav_menu">
		<ul class="tabs">
			<li><a href="#">Add/Edit Images</a></li>
			<li><a href="#">My Collections</a></li>
			<li><a href="#">My Groups</a></li>
			<li><a href="#">Others' Collections</a></li>
		</ul>
	</div>
	

I also assume that the basic list-look has already been thwarted as follows:

		div#nav_menu ul.tabs { 
			list-style-type: none; 
			margin: 0; 
			padding: 0; 
		}
			
		ul.tabs li { margin: 0; padding: 0; }
	

Preparing The List Item Links

I start by making my list items into tab-like entities by setting a width and floating them horizontally. I also tell each li to have a little bit of a margin left and right of each tab:

		
		ul.tabs li { 
			margin: 0 .5em; 
			padding: 0; 
			width: 150px;
			float: left;
		}
	

I make the anchors act more like tabs by turning our anchors into block-level elements:

		
		ul.tabs li a {
			width: 100%;
			display: block;
			padding: 4px;
		}
	

Add in background color, text color, and border...

		
		ul.tabs li a {
			width: 100%;
			display: block;
			padding: 4px;
			background: #FFFDD1;
			color: #000;
			border: 2px solid D1B863;
		}
	

...then tweak the text a little more...

		
		ul.tabs li a {
			width: 100%;
			display: block;
			padding: 4px;
			background: #FFFDD1;
			border: 2px solid #D1B863;
			color: #000;
			text-align: center;
			text-decoration: none;
		}
	

...and we're well on our way:

From Buttons to Tabs

We now essentially have buttons. To make them look like tabs we need a border running along the bottom of the tabs. You might think that the following would be good enough:

		div#nav_menu {
			border-bottom: 2px solid #D1B863;
		}
	

The problem is that when we float elements the height of the parent is reduced to zero, resulting in the following:

The trick to fill the element is to make it float either to the right or left. We can ensure the width of this element fills our entire screen width by setting the width to 100%:

		div#nav_menu { 
			float: left;
			width: 100%;
			border-bottom: 2px solid #D1B863;
		}
	

Which gives us the following:

What Would You Do?

What's the next step toward a tab-like appearance?

To make the tabs look more tab-like I want to eliminate the border on the bottom of each anchor so they don't look doubled-up:

		ul.tabs li a {
			width: 100%;
			display: block;
			padding: 4px;
			background: #FFFDD1;
			border: 2px solid #D1B863;
			border-bottom: 0;
			color: #222;
			text-align: center;
			text-decoration: none;
		}
	

The Current Page Tab

Now how about the current tab looking different from the rest? That's pretty easy, and there are two ways to do this:

  1. Give the list item for the current page an id="current"
  2. Give the body for each page a unique id, and write some body-specific CSS rules

I'm choosing method 1 for now because it's pretty straight-forward. Let's say the current page is "Add/Edit Images". We add the following id to the XHTML:

	<div id="nav_menu">
		<ul class="tabs">
			<li id="current"><a href="#">Add/Edit Images</a></li>
			<li><a href="#">My Collections</a></li>
			<li><a href="#">My Groups</a></li>
			<li><a href="#">Others' Collections</a></li>
		</ul>
	</div>
	

Then adjust the CSS to style that particular anchor differently:

		ul.tabs li#current a {
			background: #FFF;
		}
	

This is very close to what we want, but the border at the bottom of our containing div still shows up on the "current" tab, shattering the illusion.

What Would You Do?

How would you approach this problem of the border at the bottom?

  1. Use z-index and absolutely position the current tab over the container's border
  2. Use a background image to simulate a border
  3. Eliminate the border and just use a different background color

My approach is to get rid of the border at the bottom of the containing div, and replace it with a background image. This is, in my opinion, the most elegant solution. It calls for an image that is exactly 2px high and 1px wide:

This goes into the background of the div#nav_menu, positioned at the bottom and repeating along the x-axis:

		div#nav_menu { 
			float: left;
			width: 100%;
			background: url("images/border_bg.gif") repeat-x bottom;
		}
	

But now we have the reverse problem: how do we put the border back under the tabs that are not the current tab? The solution is delightfully simple:

		ul.tabs li#current a {
			background: #FFF;
			padding-bottom: 6px;
		}
	

This bumps the text of the current tab up, leaving the poor other tabs with the default padding at the bottom of only 4px. 6px-4px=2px...the size of our background border.

Effects On Hover

Because we've styled virtually every part of the presentation of each tab into the anchor element, it's easy to style the mouseover effect using the hover pseudo-element. I'll leave that to you to play around with!

Now it's time to move on to semi-graphical tabs using the sexy sexy sliding door technique.