Sep
20
2005CSS Tab Highlighting
20
2005
It’s time for another cool CSS trick. I actually learned it from “Bulletproof Web Design“, but it was only mentioned in passing, as part of a mostly unrelated section. I feel it deserves more credit, because it’s a great solution to a web design problem that’s bugged me for a long time.
The problem is this. If you have a group of navigation tabs that are pervasive throughout your site, how can you automatically highlight the tab representing the section you are in, without using different HTML code for each section?
This is a great goal to achieve, as it will enable you to use a single server-side include for your navigation tabs, (via your language of choice) and you’ll never need to tweak the logic that highlights the tabs.
In the past, I’ve resorted to using PHP code like this:
<a href="news" <? if ($mainSection=="news")
{?> class="activeLink" <?}
else
{?> class="inactiveLink" <?}?>>News</a>
It works, but it’s kind of ugly. And, I don’t like having to change server-side code whenever I make a new page. Besides, what if you’re making a site that doesn’t use server-side code at all? Then you’d have to have multiple different versions of the navigation tab HTML strewn throughout all of your pages. What a nightmare to maintain!
Here’s how to selectively highlight a navigation tab using nothing but CSS.
First, let’s assume your tabs are set up as an unordered list. This, in itself, is a fairly advanced CSS trick, but it makes for a clear example, and you can adapt this technique to DIV’s, if that’s how you’ve made your tabs.
<ul id="nav"> <li id="tab-animals"><a href="animals">Animals</a></li> <li id="tab-vegetables"><a href="vegetables">Vegetables</li> <li id="tab-minerals"><a href="minerals">Minerals</a></li> </ul>
Pretty straightfoward. Now, what we want to do is use the magic of CSS “descendant selectors” to target the appropriate tab for highlighting.
A descendant selector in CSS looks like this:
p em { color:blue; }
What this means is: in any “em” tag, which is the child of a “p” tag, apply this style (make it blue).
You can also be much more specific and specify ID’s or classes, using the usual “#” and “.” notation.
What we want to do is link up the overall page with an appropriate tag, and descendant selectors will let us do that. For example, we want to say: For the “dog” page, we want to highlight the “animal” tab.
In CSS, the most symantically appropriate place to describe the overall page is in the body tag. This is an easy place to set a “variable” of sorts, even if you’re just using vanilla hand-coded HTML. Just set the page description as the ID attribute of the body tag.
<body id="dog"> [...] </body>
Well, we have our “dog” page. So, now how do we highlight the “animal” tag? Well, first, let’s define some drastically simplified CSS for both a highlighted and non-highlighted state. Let’s just assume the highlighted tab is yellow, and the non-higlighted tab is gray, like so:
Highlighted:
color: yellow;
Non-highlighted:
color: gray;
First, we target all the tabs and make them gray (again, using descendant selectors - this time invoving the ul tag with the ID of nav
#nav li { color: gray; }
Now, we can set up a list of page/tab relations (including our dog/animal example) which will override this style and highlight the appropriate tab - we just separate the selectors with commas:
body#dog li#tab-animals,
body#cat li#tab-animals,
body#cow li#tab-animals,
body#carrot li#tab-vegetables,
body#celery li#tab-vegetables,
body#diamond li#tab-minerals
{ color: yellow; }
There are many ways you can modify this technique to your needs. You may want to specify the appropriate tab using a class instead of an ID on the body tag, for example. This way you wouldn’t need to change the CSS file every time you make a new page. Regardless of where you go with it, this technique is a fantastic way to “dynamically” change your layout without a shred of actual code.
Sweet! I can’t tell you how much work this will save me. So I won’t. At all. Thanks for the great tip though - keep it up.
Mike 9/21/05 @ 11:03 am