Setting the current menu state with CSS
Every now and then I get an email from someone asking me how to use CSS to set the current state for a menu bar. Both the Inverted Sliding Doors tabs technique that I wrote about last summer and the navigation bar on this site, described in Turning a list into a navigation bar, use CSS to set the current state.
It isn’t very complicated and has been described elsewhere, but to have somewhere to refer people asking about it I’ve written a quick explanation of how it works.
It’s really quite simple, and I’ll use this site as an example. There are a few main sections on the site: Home, About, Archive, Lab, Reviews, and Contact. These sections make up the top menu and are marked up as an unordered list, with each list item given a unique id:
<ul>
<li id="nav-home"><a href="/">Home</a></li>
<li id="nav-about"><a href="/about/">About</a></li>
<li id="nav-archive"><a href="/archive/">Archive</a></li>
<li id="nav-lab"><a href="/lab/">Lab</a></li>
<li id="nav-reviews"><a href="/reviews/">Reviews</a></li>
<li id="nav-contact"><a href="/contact/">Contact</a></li>
</ul>
The body of every document is then given an id that reflects which section it belongs in: <body id="home">
, <body id="about">
, <body id="archive">
, <body id="lab">
, <body id="reviews">
, and <body id="contact">
.
Note: if you look at the source of this site you’ll find that I’ve used class
instead of id
. That’s because the id
is used for my CSS signature. It doesn’t really matter which you use as long as you’re consistent.
With the markup in place, you need to write one or more CSS rules to match the body
id
with the correct list item id
. Again, using the navigation bar of this site as an example, the styles are applied to the links within the list items:
#home #nav-home a,
#about #nav-about a,
#archive #nav-archive a,
#lab #nav-lab a,
#reviews #nav-reviews a,
#contact #nav-contact a {
/* declarations to style the current state */
}
You may need an additional rule to style the :hover
state of the current item. In this case the selectors would look like this:
#home #nav-home a:hover,
#about #nav-about a:hover,
#archive #nav-archive a:hover,
#lab #nav-lab a:hover,
#reviews #nav-reviews a:hover,
#contact #nav-contact a:hover {
/* declarations to style the hover effect of the current state */
}
That’s all there is to it. The above rules only take effect when the body
id
matches that of a list item. Otherwise nothing happens.
This is a nice and simple trick that’s useful when you can’t use server side logic to insert a class
or an id
into the list item that holds the current menu item.
- Previous post: Efficient CSS with shorthand properties
- Next post: CSS tips and tricks, Part 1