Recently had a project land on my desk that required tabbed navigation that overlap one another. Just so we're clear on what we're doing: here's the demo. Here is how I did it:
1) Each tab has four "states" – Off, Off (with right tab on), On, On (with right tab on). I combined each of these four states in the one image for each tab. So it looks like this:
2) The HTML is pretty simple and looks like this:
<div id="navbar">
<ul>
<li id="nav_home"><a href="#"><span>Home</span></a></li>
<li id="nav_about"><a href="#"><span>About Us</span></a></li>
<li id="nav_products" class="right"><a href="#"><span>Products</span></a></li>
<li id="nav_sales" class="current"><a href="#"><span>Sales Reps</span></a></li>
<li id="nav_contact"><a href="#"><span>Contact Us</span></a></li>
</ul>
</div>
Notice that when one of the tabs is set as the "current" tab – we also need to define the tab before it with a class of "right" (meaning that the tab to the right of this one is set as "on")
3) Then we define the various states in CSS. In this case, all the tabs are the same width and height:
#navbar li {
float: left;
}
#navbar li a {
display: block;
height: 29px;
width: 91px;
}
Hide the text with css since we're using images for the tabs:
#navbar li a span {
margin: 0 0 0 -100000px;
}
Define the image to be used for each tab:
#nav_home a {
background:url(images/nav_home.gif) top left no-repeat;
}
#nav_about a {
background:url(images/nav_about.gif) top left no-repeat;
}
#nav_products a {
background:url(images/nav_products.gif) top left no-repeat;
}
#nav_sales a {
background:url(images/nav_sales.gif) top left no-repeat;
}
#nav_contact a {
background:url(images/nav_contact.gif) top left no-repeat;
}
4) I'm going to skip over the rest of the class definitions and move to the jquery part – because I think it will make more sense to see how the classes are being defined if you see what class I'm applying when and where.
<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
<script type="text/javascript">
var j = jQuery.noConflict();
j(document).ready( function() {
j('#nav_about a').hover(function() {
j('#nav_home a').addClass("left");
}, function() {
j('#nav_home a').removeClass("left");
});
j('#nav_products a').hover(function() {
j('#nav_about a').addClass("left");
}, function() {
j('#nav_about a').removeClass("left");
});
j('#nav_sales a').hover(function() {
j('#nav_products a').addClass("left");
}, function() {
j('#nav_products a').removeClass("left");
});
j('#nav_contact a').hover(function() {
j('#nav_sales a').addClass("left");
}, function() {
j('#nav_sales a').removeClass("left");
});
});
</script>
So what I'm doing here is, anytime I mouseover a tab, I'm adding the class "left" to the <a> tag in the tab in front of the one my mouse is on.
So if the tab in front of the one my mouse is on is "off" – then we need to change that tab to state #2 (Off – with the tab next to it on). If that tab has the class "current" applied to the li tag – then we need to move that tab to state #4 – (On – with the tab next to it on).
4) So on to the various states with css….
When hovering – we go to the "on" state – (in this case, when tab is current, it lookes the same as when we mouse over it.) So the most basic state – state #3: Whether the tab is current, or hovering – move to that "Third" state: On – with the tab next door off.
#navbar li.current a,
#navbar a:hover {
background-position: 0 -58px;
}
This is for state #2: Off – with the tab next to us as On. (the ".right" class applied to the li tag means that the tab in front is "current")
#navbar li.right a,
#navbar li a.left {
background-position: 0 -29px;
}
This is for state #4 – On with the tab next to us as on.
#navbar li.right a:hover,
#navbar li.current a.left {
background-position: 0 -87px;
}
One thing to note – the last tab really only has two states – because there is no tab in front of it – but to keep things simple in the code and css – I just made the image with the extra versions. This way it could have the same styles applied to it – without having to make a special case for it.
Here are some more demos:
No tab set as current
Home tab set as current (no "right" class needs to be applied – since home is the first tab)
Last tab set as current