Image based navigation has an (understandably) bad name in the web industry but there are steps you can take to make it work. This post will result in this:
You can achieve some beautiful effects with image based navigation – just look at Matt Mullenweg’s website. There are pitfalls, however, often there’s a second or two of flickering where the rollover background loads which creates a disjointed experience. Also, whether, Like Matt, you want to create a hand-drawn aesthetic or you just want to use a non-standard font for your navigation (like Blue Door Baby or Bush Theatre) you still have to be sure that you’re making your navigation accessible. Just because a person can read your image, doesn’t mean that Google can, or a screen reader, or that it will be visible on a mobile device or if someone has CSS disabled. So how do we make sure that it’s pretty, doesn’t flicker and is accessible? Allow me to explain:
We shall start with generic navigation markup. It’s an unordered list, or <ul> because that’s the generally accepted markup for XHTML navigation nowdays.
<div id="Navigation">
<ul>
<li><a href="home">Home</a></li>
<li><a href="about">About</a></li>
<li><a href="site">Site</a></li>
<li><a href="contact">Contact</a></li>
</ul>
</div>
Obviously that wont be sufficient to convert to images so we’ll have to add a few more tags and some classes. For example:
<div id="Navigation">
<ul>
<li class="home"><a href="home"><span>Home</span></a></li>
<li class="about"><a href="about"><span>About</span></a></li>
<li class="site"><a href="site"><span>Site</span></a></li>
<li class="contact"><a href="contact"><span>Contact</span></a></li>
</ul>
</div>
I’ve added the class to the <li> tag so that we can assign the image individually to each list item. I’ve also added a <span> to each of the list items, but we’ll get to that later.
Here’s an image of the (seriously lacklustre) menu that I’m trying to create:

This is where we tackle the flickering problem. To do this we use CSS Sprites. The image we use will be just one image and it will contain both the plain and the hover states. So I created the hover states of my menu items by changing the colour and adding some hearts with brushes from Ego Box. And so my final image is as so:
So we can start styling our list. This is the first step:
#Navigation ul {
list-style-type:none;
}
#Navigation ul li {
float:left;
}
#Navigation ul li a {
display:block;
background:url(images/menubg.jpg) no-repeat 0 0;
width:125px;
height:60px;
}
I’ll go through what I did briefly. You probably wont need to read this if you know your CSS basics
- I set the list-style-type to none to remove the bullet points
- I made the list items float to the left so that they don’t stack on top of each other any more.
- I set the a tag to display block (so that it recognises the width and height)
- I made the background image out menu background image
- And I set the width and height.
Now I have something that looks like this:

So next we need to make each list item say the right thing. We do this by moving the background image a certain number of pixels to the left. Unless all of your menu images are the same size, this is a very manual process, I generally use the rulers in Photoshop to tell me how many pixels I need to move it by. I know that the “Home” image is 125px wide so I know what the CSS for the “About” image will be:
#Navigation ul li.about a {
background-position:-125px 0;
}
All I’m doing is moving the background image 125 pixels to the left. Now when I do this for all of the images it looks something like this:
#Navigation ul li.about a {
background-position:-125px 0;
width:133px;
}
#Navigation ul li.site a {
background-position:-258px 0;
width:97px;
}
#Navigation ul li.contact a {
background-position:-355px 0;
width:145px;
}
I have also added the widths. I now have something that looks like this:

To get rid of the unsightly text all we have to do is set it to display:none like so:
#Navigation ul li a span {
display:none;
}
“Why even add it then?” I hear you ask. Same reason we add alt to <img> tags: Accessibility. Yes, it is important.
Yay, now we have a pretty image based menu so the last thing to do is create the hover state. We do this by moving the background image up by the height of the menu, in this case it’s 60px
#Navigation ul li a:hover {
background-position:0px -60px;
}
That’s it! Now you have yourself an gaudy, unflickery, accessible image-based menu
The complete CSS:
#Navigation ul {
list-style-type:none;
}
#Navigation ul li {
float:left;
}
#Navigation ul li a {
display:block;
background:url(images/menubg.jpg) no-repeat 0 0;
width:125px;
height:60px;
}
#Navigation ul li a:hover {
background-position:0px -60px;
}
#Navigation ul li.about a {
background-position:-125px 0;
width:133px;
}
#Navigation ul li.about a:hover {
background-position:-125px -60px;
}
#Navigation ul li.site a {
background-position:-258px 0;
width:97px;
}
#Navigation ul li.site a:hover {
background-position:-258px -60px;
}
#Navigation ul li.contact a {
background-position:-355px 0;
width:145px;
}
#Navigation ul li.contact a:hover {
background-position:-355px -60px;
width:145px;
}
#Navigation ul li a span {
display:none;
}
