No silly javascript, no crazy coding, no waiting for images to load. Just some good old fashioned HTML, CSS, and a single image. Once you do this, you’ll never make your web site navigation any other way.
Warning: If you aren’t into front-end coding for the web, you may want to skip this. For those that are (I love you that much more), this has been covered elsewhere and covered much better, so hopefully this is old hat.
Can’t wait for the results? Here’s the final navigation with CSS image replacement, used in the real world. Please, disable styles, view source.
How to do it
First, you should already be in the habit of making your navigation using unordered lists. If you’re not doing it, now is the time to start.
Setup your navigation in an unordered list:
<ul>
<li><a href="#">Navigation item 1</a></li>
<li><a href="#">Navigation item 2</a></li>
</ul>
Next, add a little CSS to control your list items:
ul li {
display:block;
float:left;
list-style-type:none;
}
Such basic CSS results in:
With just some margin & font adjustments, you could stop here & you’d have yourself a nice clean navigation for your site. But only nerds (and search engines) want basic HTML navigation like that. We’re here to please our designers and clients. Let’s turn this basic HTML into something so sexy they’ll shed tears over at first sight. Something like this maybe:

“Oh, and can you make it kind of POP on hover?”
Why yes; in fact we can.
Make yourself an image that contains both the :link state & :hover state of all your navigation items. Better yet, teach your graphic designer to do this for you. In the example below, the :link states are on top and their :hover directly below. Both areas must be the same height.
Here’s what the image looks like, with some guides:

You’ll then export that file & use it as a background-image for all the links in your unordered list. Here’s where your guides come in handy. In this example, the link area has a height of 66 pixels and the first list item is 34 pixels wide, so we’ll setup some CSS defaults for the anchor tags:
ul li a {
display:block;
height:66px; width:34px;
background:transparent url(navigation.png) no-repeat 0 0;
text-indent:-9009px;
}
You’ll notice the text-indent:-9009px; That pulls the text out of sight and out of mind. Make way for your pixel princess!
My second list item is wider, so let’s give that one an ID and change the width. We also need to pull the background-image 34 pixels to the left, since that’s where the image for the second list item starts.
<ul>
<li><a href="#">Navigation item 1</a></li>
<li id="navigation2"><a href="#">Navigation item 2</a></li>
</ul>
ul li#navigation2 a {
width:60px;
background-position: -34px 0;
}
Now our regular old HTML unordered list is starting to get somewhere:

Now for the :hover & the real magic
All that’s left is to move the background-image on :hover. Since our list items have a height of 66 pixels, we’ll move the background-image up 66 pixels for each list item:
ul li a:hover {
background-position: 0 -66px;
}
ul li#navigation2 a:hover {
background-position: -34px -66px;
}
You’ll now have the start of one sweet ass, simple navigation:
Throw some margins in there for spacing, or add whatever tweaks you deem necessary. The final step is to laugh at how simple this is, and never look back.
Carry this same process throughout the rest of your navigation and you’ll end up with something so search engine friendly you’ll now be crying along with your client.
Here’s the final navigation with CSS image replacement, used in the real world. Please, disable styles, view source. If you look carefully, you’ll notice that once the client asks you to change the order of the list items, it’s as simple as moving around your LI’s in the HTML into any order you’d like.
If you have improvements, ways to make this more efficient, or you’d just like to share how long you’ve been using this technique for and how old it is; Please, leave your comments.
Update:
To get your hover state to stay in the hover state, to mark the users currently selected page for example, I like to use an ID or class on the body tag.
For example, on a contact page add:
<body id=”contact”>
And in your CSS hover state, add a line for body#contact:
ul li a:hover,
body#contact ul li a {
background-position: 0 -66px;
}
Did you find this post helpful?
I’ve used the same technique on my site …
[…] phil showed this to me with his uncle’s splashguard site. this site ghetto cooler goes into detail. […]
[…] keeping it simple… http://ghettocooler.net […]
Used the same technique on a site I made a few weeks ago.
I did though, begin to wonder if it would be easier to have each as an individual image rather than one big image for all (so that background-position changes could be applied to all [the x values would be 0 for all]).
When you have say 7 menu items each with a different standard image, a :hover, :active, :focus, and selected page, the CSS background-positions start to add up.
hahahah!
that was easy. heard about it about a month ago. But this is the first place that described how it works. Thanks.
[…] Simple Navigation with CSS Image Replacement […]
I’ve followed your instructions, image replacements works nicely, BUT my navigation div is 800px as is the sum of all my ’s, as you can see (http://www.puregraphx.be/security) the last list item is thrown to the next line. Please help!
Thanx
WOW! Works like a dream as you said!
BUT… How do you get a image to stay like the hover state. If your in that section. so the navigation button stays highlighted. like apple :o)
I have tried creating a style with a different name which I change on each section to say highlight this.. with the same styles as the a:hover but it doesn’t work??
might be a good addition to this code?
Thanks
Mark - What you need to do, is on each of your sites pages, add an ID or class to your body tag.
For example, on a contact page add:
body id=”contact”
& in your CSS hover state, add a line for body#contact:
ul li a:hover,
body#contact ul li a {background-position:xxx;}
Make sense?
This is awesome! But my question is, how would you center a navbar like this? I have one made, but I can’t get it to center on the top.
Phrequencyviii - you would center the entire UL, perhaps by putting it in a block that has text-align: center in it, and setting your UL to have right & left auto margins with a set width.
Something along these lines:
div.nav-wrapper {text align: center;}
ul {width: 200px; margin: 0 auto;}
Thanks for the great tutorial! When I try to get the hover state to stick on each respective page though, all list items in my unordered list flip to the same hover state. Any idea why? Thanks again.
Damn, right when I sent the email earlier I figured it out.
Thanks, it works great!!!!!
I’ve do it, but text indent works just on IE.6 none on Firefox or IE.7. Anybody know why?
Hi, the navigation works great in IE however in firefox when I click on a section of the navigation I get a grey outlined box Which seems to be showing where the full image would be. Does anyone else get this? if yes how can I get rid of this? Any help would be greatly received.
Thanks!
I’m sorry if this sounds really stupid, but I’m making myself nauseus b/c I can’t figure out how you get the background positions after the first one that is -34. That one is obvious b/c that is the width of the 1st image, but then the next one’s background position is -241, the next is -94… and I can’t figure out where you got those numbers from, nor do you explain it in your tutorial b/c you only do the first one… those background position numbers make no sense to me. Please help! Can you please add more than the 1st image to the set, so I know how you get all those other background position numbers?