Centered 3 State Tabs with CSS
7 July 2006
Last December, 24Ways and Ethan Marcotte gave us a way of creating centered navigation tabs based on the infamous ‘Sliding Doors’.
Never ones to look a gift horse in the mouth, we took this technique and added “hover” and “current” tab states into the mix. We know we’re not the only ones to adapt the centered tabs in this way, but still feel that its worthwhile examining the technique.
Here’s a sneak preview of the finished tabs.
Assuming that you’ve already read the original article (hint: now is a good time to do so, if you haven’t), we’re going to dive straight into our simple list of navigation links.
<ul id="nav"> <li><a href="/"><span>Home</span></a></li> <li><a href="/work"><span>Work</span></a></li> <li><a href="/about"><span>About</span></a></li> <li><a href="/contact"><span>Contact</span></a></li> </ul>
Really we should be able to manage without the extra <span> tags, but given IE’s reluctance to apply the ‘hover’ state to anything except links, the spans are a necessary evil.
Next we apply some basic styles to the list, as below, which center the list elements and lay them out horizontally, rather than vertically:
ul#nav, ul#nav li {
list-style: none;
margin: 0;
padding: 0;
}
ul#nav {
text-align: center;
padding: 5px 0 6px;
}
ul#nav li {
display: inline;
margin: 0 .35em;
}
ul#nav a {
padding: 5px 0;
text-decoration: none;
}
ul#nav a span {
padding: 5px 1em;
}
The Images
As within any “Sliding Doors” based navigation list, we need separate images for the left hand edge and the rest of the tab (i.e. the middle and right hand edge).
We’ve created just two images [image1] [image2] that provide all three states for our tabs: “normal”, “hover” & “current” (or “active”). Having all three states represented in these images avoids any delays in loading the hover state images and any need for image pre-loading scripts.
With the “normal” state colour at the top of our two images, our horizontal links are quickly restyled as tabs:
ul#nav a {
padding: 5px 0;
text-decoration: none;
background: url(./buttons_right.jpg) no-repeat right top;
}
ul#nav a span {
padding: 5px 1em;
background: url(./buttons_left.jpg) no-repeat left top;
}
We’re also going to use a 1 pixel square image, the same colour as our tab outlines, which will represent the bottom border of our navigation.
ul#nav {
text-align: center;
padding: 5px 0 6px;
background: #fff url(./nav_bottom.gif) repeat-x bottom;
}
How are we doing so far? Not bad.
No Bother With Hover
When a visitor moves his/her mouse pointer over a tab, we want the tab to change colour. This “hover” effect is very simple to achieve because we’ve already included a hover state in our existing tab images. Therefore, knowing that, for this example, each tab state is 50 pixels in height and our hover state is the second state in the image, we just need to adjust the background image position to raise it by 50 pixels.
ul#nav a:hover {
background-position: 100% -50px;
}
ul#nav a:hover span {
background-position: 0 -50px;
}
Note that we’ve also changed how the horizontal position is defined. This is because the Web Standards don’t allow us to mix the named positions (“right”, “left”, “center” etc.) with pixel value positions, even though most browsers seem to support this anyway. However, you can mix pixel values with percentages, so here we’ve used “100%” instead of “right” and “0” instead of “left”.
You are Here
The last step in creating our tabs is creating the “current” or “active” state tab which will indicate to the visitor which section they are current in. Having already seen how to create the hover state in CSS, its not hard to work out how we’ll create the current state.
The trick here is getting the (X)HTML to tell us which tab to apply the “current” state to and there are two different ways in which we can achieve this:
- Active Class
If your navigation is included in the (X)HTML code for each individual page, then you can “hard-code” the current tab, using a class to apply the “current” state, e.g.
class="active".Its also possible to use this method with certain Content Management Systems that can add IDs and classes to your navigation elements depending on the section of the site that the visitor is currently viewing.
Using this method, the “current” tab can then be referenced, in CSS, using
ul#nav a.active- Body ID
This approach does not rely on either hard-coding or dynamically updating the current tab within the navigation code. Instead each “tab” link is given a unique ID, e.g.
id="tab-work"and an ID is applied to the<body>tag for each section of the site, e.g.id="section-work". It is then the combination of these IDs that helps to determine the “current” tab.Using this method, the “current” tab is referenced, in CSS, using
body#section-home ul#nav a#tab-home, body#section-work ul#nav a#tab-worketc.
For simplicity, we’re using the active class approach in our example.
We know that we need to move the background tab images up by another 50 pixels, i.e. 100 pixels from their original position. However, we also want the current tab to bleed through our bottom border to emphasise the tab effect and achieve this by adjusting the padding. Therefore, the CSS code for the current tab is as follows:
ul#nav a.active {
padding: 5px 0 6px;
background-position: 100% -100px;
}
ul#nav a.active span {
padding: 5px 1em 6px;
background-position: 0 -100px;
}
Finally, we need to adjust some of the padding rules to make sure our tabs look good in IE6 too.
* html ul#nav a, * html ul#nav a.active {
padding: 0;
}
We’ve used the ”* html” hack here to ensure that only IE will apply this rule, however thats only because we want to keep all of our CSS in one place for the purpose of this example. For real projects, creating seperate style sheets for the IE related fixes and loading them using conditional comments is a much safer bet.
Update: As the ”* html” hack does not work for IE7 and if you prefer not to use conditional comments, then you can use a rule such as ”*:first-child+html {}” instead. The completed CSS, below, has been updated to include this.
This now gives us our completed CSS:
ul#nav, ul#nav li {
list-style: none;
margin: 0;
padding: 0;
}
ul#nav {
text-align: center;
padding: 5px 0 6px;
background: #fff url(./nav_bottom.gif) repeat-x bottom;
}
ul#nav li {
display: inline;
margin: 0 .35em;
}
ul#nav a {
padding: 5px 0;
text-decoration: none;
background: url(./buttons_right.jpg) no-repeat right top;
}
ul#nav a span {
padding: 5px 1em;
background: url(./buttons_left.jpg) no-repeat left top;
}
ul#nav a:hover {
background-position: 100% -50px;
}
ul#nav a:hover span {
background-position: 0 -50px;
}
ul#nav a.active {
padding: 5px 0 6px;
background-position: 100% -100px;
}
ul#nav a.active span {
padding: 5px 1em 6px;
background-position: 0 -100px;
}
* html ul#nav a, * html ul#nav a.active {
padding: 0;
}
*:first-child+html ul#nav a,
*:first-child+html ul#nav a.active {
padding: 0;
}
The Finished Tabs
Enjoy!
Article Tags: buttons, design, examples, how-to, navigation, tabs, xhtml, css
About Citrus Skies
Citrus Skies is a small web design studio located in Belfast, Northern Ireland, that designs and creates simple, attractive, effective websites. learn more
