I discovered two of my most often used CSS techniques at the same place - Petr Staníček's Wellstyled.com (Staropramen, Budvar, Pilsner Urquell, great CSS techniques - gotta love the Czechs 😉 ). And those techniques are an image replacement (IR) technique that I later found out was actually called the Gilder Levin method and the use of a single image for creating CSS rollovers without the need for preloading images.
What was missing from the two tutorials, however, was an example that showed how the two could be combined. Something else that I couldn't find a tutorial for when I first went looking at how to do it was a way to combine the previous two examples when making a navigation bar. In other words, using a single image for both normal and hover states for all links in an image-replaced navigation bar. And then adding to that the added accessibility of incorporating the Gilder Levin IR technique.
I still haven't come across a tutorial that combines all that, so I thought I'd do one myself to help out anyone who might be looking to do the same thing.
I'm also going to provide an example of how to incorporate all of that and add another popular CSS technique to the mix as well - Sons of Suckerfish Dropdowns.
First of all, it might help to look at the example to give you an idea of what I'm talking about. The image that we're going to be using to create the navigation bar (horizontal in our case, but the same techniques could be applied to a vertical example) is below:
The HTML for this is fairly simple:
Without any styling, it gives us this:
class="nav IR" is because we’re attaching two classes to the list: one for styles specific to the navigation bar we’re creating and the second with general image replacement styles that can be used elsewhere (either on the same page or across a site).
The classes for each of the links are so that we can style each link with its individual image. I’d normally use IDs for this sort of list, but as the example shows two variations of the same list, I’ve used classes instead. (IDs can only be used once per page. If you want to reuse styles, you need to use classes.)
So, let’s look at the CSS:
position: relative on
ul.IR li is to establish a new positioning context for the elements contained within. In this case, it’s the
em which we’re going to place at the top corner of each list element with
position: absolute so that it in fact covers up the text underneath. We need to set the
display: block because it’s an inline element and won’t take dimensions in its default state.
The IR technique I’m using is actually an updated version of the one that I first discovered on Wellstyled.com and irons out a few bugs that IE5/Mac had with the original. The updated method is called the Gilder Levin Ryznar Jacoubsen IR method. I’ve removed a couple of styles relating to
overflow: hidden for this example because it will prevent our Suckerfish dropdowns showing in the second example. The
overflow: hidden is to prevent the text peeping underneath the images when you resize the text and it can be controlled fairly well by setting an appropriate
* html>body styles only affect IE5/Mac and the explanation of why they’re necessary is given in full at the link above.
So that sets up our IR styles, now we can start styling the list itself.
First, we remove the bullets from the list, then we float the list items to the left so that they are all on the same horizontal plane. We then give the same dimensions to both the list items and the
ems that will hold the images. In this case, the height is a little over half the height of our actual image because we only want the top half to appear in the normal state (the rollover state remains hidden below). The actual width of the whole image is 441 pixels, but we only want a third of that to appear within each link. (All my links are the same width because the word is nearly the same, but for real-life situations with words of different lengths, you’d probably need to give each list item and its associated
em a different width.) A little bit of bottom padding may also be required to give the list item area enough depth to ensure that the submenus don’t disappear too quickly when trying to roll over them.
Then we apply the
background-image to each of the
ems. We need to apply the
background-image to each individually because we’re going to be manipulating the
background-position of the image for each one (see below).
cursor: pointer; is needed for IE which won’t show the normal ‘hand’ cursor when hovering over the links with this IR method. (For IE5+ you need to use
cursor: hand; which, unfortunately, doesn’t validate, so you may want to move it to an IE5-only stylesheet accessed by conditional comments.)
Now, we’re going to position the background image in each list item.
For the first item, we want it and the background image to be at the 0 position both horizontally and vertically. The
li:hover moves the background image vertically, moving the normal state out of view and bringing the rollover state on screen.
IE doesn’t accept
:hover on any elements other than pseudo elements. To get it to work for other elements, we need something like the whatever:hover and attach it to the
body like so:
For the second and third list item, we move the position of the list item horizontally and then use a negative horizontal position to bring the right part of the image into view. A good way of getting the positions right is to place the actual image temporarily on your page while you’re getting the layout right so that you can line up your menu with the image.
And what we end up with is Example 1.
Adding the dropdown
And the additional CSS:
We set all the anchor tags to
display: block; so that they’re all the same width. We use the Holly Hack to correct a hasLayout problem with IE6 which led to problems with accessing the dropdown links.We have already set the positioning context for the image replaced list items, so the descendant unordered lists – the dropdowns – are placed absolutely relative to their parents. The
left: -999em; places them off-screen in their normal state with the
li:hover bringing them back into view.
We need to reset the height and padding on the descendant list items because they were set for the image replaced list items. The rest of our styles are simply to get the dropdown list items to look the way we want.
And that’s it. As mentioned previously, in real-world situations there’s probably quite a few things that would change, particularly to do with the width of the image replaced list items and maybe their descendant dropdowns too.