CSS Text based navigation bar with images
— Although navigation bars can be styled very pretty using only text and CSS sometimes circumstances might require them to be image based. The problem this brings is that it’s not good at all to have the navigation’s markup to be actually made of linked images, being one of it’s biggest issue that search engines and screenreaders wouldn’t be able to pick up the text in those images. And it gets even worst if it have to be animated as most of the solutions for that would require Javascript. Having that said, in this short article I will hopefully show you how I create these animated imaged based, navigation bars in an clean and accessible way using images and CSS.
Update:
I have released a system to easily generate the code you need to build this technique. Visit the CSS Navigation Bar Code Generator.
Preparing the XHTML:
Ok, lets pretend we need to have the following buttons: Home, Services, About Us and Contact Us. We will use a list to create the navigation bar, as navigation bars are a list of links, so they should be marked up as such:
<ul id="topnav"> <li id="topnav-1"><a href="home.html" title="Home">Home</a></li> <li id="topnav-2"><a href="services.html" title="Services">Services</a></li> <li id="topnav-3"><a href="about-us.html" title="About Us">About Us</a></li> <li id="topnav-4"><a href="contact-us.html" title="Contact Us">Contact Us</a></li> </ul>
You might notice that we gave unique ids to the list and it’s elements to be able to style them separately, we will get into that later.
Image buttons:
Now lets get our hands on the images. I like to use the “sprite image technique”, because it reduces files count, often reduces file size ( which saves bandwidth ), speeds up page load times, makes it easier to maintain and plus it’s fun!. For this example I made a very simple 480×40px navigation bar, let’s take a look at it:

You can see that we have in one image the three instances of the navigation bar with all its buttons. These instances cover the three possible buttons state we need: normal, over and current.
CSS VOODOO:
Here comes the magic ingredient, the CSS. We will use CSS’s power to position each button and instance of our navigation bar image in its own link. First, we start by setting up the list ( navigation bar ) width and height and then removing the item bullets and telling the list to display the items side by side:
/* TOP NAVIGATION BAR
/////////////////////////////////////*/
ul#topnav {
width:480px;
list-style:none;
height:40px;
}
ul#topnav li {
display:inline;
}
The following step is to add the general rules for the links. We gonna float them to the left, shift their text -9999px to hide it put it out of the screen:
ul#topnav li a {
height:40px;
float:left;
text-indent:-9999px;
}
Now as each link has a different width size and background portion we gonna assign the correct values to each of them with width and the CSS background property. I made a simple schema to show you from where I get values we will use:

ul#topnav li#topnav-1 a {
width:106px;
background:url(images/nav.jpg) no-repeat 0 0; /* X and Y position at 0 */
}
ul#topnav li#topnav-1 a:hover {
background-position:0 -40px; /* Y position -40px for Over instance image */
}
ul#topnav li#topnav-1 a.current {
background-position:0 -80px; /* Y position -80px for Current instance image */
}
As you may see above, we defined 3 rules for the first button: #topnav-1. First rule sets the width of the link and its default background. Second rule, a:hover changes the background’s Y-position to -40px for the over state and lastly the a.current changes the background’s Y-position to -80px for the current class effect.
Now to set the rest of the buttons we will follow the same workflow, keeping in mind that each button have its own width and background X-position. A very quick easy way to get this last value is to get the previous button background X-position and its width and substract them. For example:
#topnav-2 will be: 0 ( previous button background X-position ) – 106px ( previous button width ) = -106px.
#topnav-3 will be: -106px ( previous button background X-position ) – 116px ( previous button width ) = -222px.
ul#topnav li#topnav-2 a {
width:116px;
background:url(nav.jpg) no-repeat -106px 0;
}
ul#topnav li#topnav-2 a:hover {
background-position:-106px -40px;
}
ul#topnav li#topnav-2 a.current {
background-position:-106px -80px;
}
ul#topnav li#topnav-3 a {
width:122px;
background:url(nav.jpg) no-repeat -222px 0;
}
ul#topnav li#topnav-3 a:hover {
background-position:-222px -40px;
}
ul#topnav li#topnav-3 a.current {
background-position:-222px -80px;
}
ul#topnav li#topnav-4 a {
width:136px;
background:url(nav.jpg) no-repeat -344px 0;
}
ul#topnav li#topnav-4 a:hover {
background-position:-344px -40px;
}
ul#topnav li#topnav-4 a.current {
background-position:-344px -80px;
}
CONCLUSION:
There you go, a quick and clean solution to create a text based navigation bar that visually looks like an image based solution with over and current animation using only XHTML, CSS and one image. I hope you find this post useful!
This technique has been tested in: IE6, IE7, Firefox ( Mac/PC ) and Safari ( Mac ).




Nice article! :)
One thing… Because support is so inconsistent between current and older browsers it’s not a good idea to use underscores in class or ID names. I’ve heard that old V’s of Navigator don’t recognize it – same with some old versions of Opera too.
Thanks for the heads up James! Post updated. Will surely take this into consideration in future projects.
thanks for the so good explanation that you have done in this tutorial. :)
Woah, you’re first article is a pretty solid ressource. Keep it up!
Thanks for the kind words :)
Greeting Matt. Thanks for this great article. It deserves all the attention its getting. Cheers :)
Very nice!!
omg! thanks so much for this template. I’m a beginner/intermediate designer and I’ve been searching for help with an image based nav bar for a week now. Very easy to follow and the graphic was most helpful in grasping the whole concept….especially background position x & y coordinates.
thanks again!
great article,many thanks
Thanks for your comments :)
Thank you!! this is an excellent article man, this save me a lot of time, greeting from Costa Rica =)
Hi Matt, this is great! This post has been really helpful. I’m just a beginner but your text is as clear as water. One doubt, though.
Is it possible to use this with more that 5 links/buttons? I ask you because I managed to make it work with 5 (I was aiming 7 but the last 2 don’t show up) and I don’t seem to be able to get my 7 buttons.
I need a yes-or-no answer, if itś a yes I’ll keep on trying.
Thanks in advance, martin.
Hi Martin, Thanks for stopping by, im glad you found the tutorial useful. The answer is Yes you can. As for this first time you could try using the CSS Navigation Bar Code Generator and then investigate the generated code.
Cheers!
Thanks Matt, I’ll just do that and go from there. I gave it a try last night but it was really late and I don’t think my lights were on at that time! :)
Thanks for your answer.
Done it! Thanks a bunch! The only thing I can’t get to work yet is the “current state”. It doesn’t change when I change the pages or whatever but I still need to see how that works.
Thank you for these tutorials!
Thanks for excellent work.
I’ve got the problem, trying create horizontal menu. After uploading my JPG file (GIMP-created) , there is only one option “VERTICAL” and further work does not have sense.
Hi Tomasz. Thanks for the nice words.
Is your horizontal navigation bar vertical height divisible by two or three? if you want send me then image to contact@mattvarone.com and i will check it out.
Hi Matt,
Thanks for your excellent work! Very easy and user-friendly. It was fantastic : I had no problems making the navbar and then locally substituting GIFs for the JPEGs (they were too muddy, sadly).
However I am having issues getting the navbar to center on my page, under the header image : it’s too far to the right. I’ve enclosed it in a div called “nav”, but that doesn’t seem to make any difference… Also, there seems to be a vertical space of 10-12 pixels above the navbar, and I can’t figure out where it’s coming from.
I’m more of a Flash developer than HTML, and I’d appreciate a little help on this if you have a second. I can return the favour one day if you ever need Flash help or advice :-)
The pages and the associated stylesheets are online here :
http://clients.pixelligence.com/citiblocs/mockup/
Would you mind taking a look?
Thanks VERY much in advance!
cheers,
Ric Zito
Great tutorial!
Thanks!!
Thanks, I tried the generator and it works great. I cannot open the downloaded zip file though? Any way to make this work?
Hi RM, thanks for the comment. See if you can try decompressing the zip file with another program. I noticed some treat the file as corrupted but havent got to look much into it. Let me know if that worked for you.
Yes, that worked. Thanks for your help! Now if you would please allow this thing to upload png files, I’d be stoked.!
Im not sure if it would be easy or not to use your generator and then match up my png files to your generated jpgs…
Thanks!
I get that you can design how your nav bar would look using css but what I don’t understand is how you go about changing 100 pages in a site when a customer wants to add or delete a button? css is just for the design aspect, no? I just had this client ask me to get rid of her “purchase” page. Luckily there were only 20 pages in her site – but it got me to thinking, what if there were 100 or something. I had to go into each page and delete that button. should I use a template for the buttons? or is there something in css class I missed. Thanks…
That saved a bit of time – thanks for the useful tool Matt.
Sweet tutorial! Coming from someone without much experience in this regard, I found it really easy to follow. Any thoughts on the best way to integrate this type of navigation with content below it? I’m told iFrames are not the way to go anymore, but am curious the best way to preserve the page state without recreating the menu on each page so the “active” page remains active (the image shows the proper page as being active)
You bloody genius, been looking for this everywhere. Plenty tutorials on the rollover bit, but the part i was stuck on was maintaining the a ’selected’ state for different pages, which you fixed so simply.
Hi,
My nav bar wasnt centering in Safari, so I set it’s margin-left to -40px. It looks all right in Safari but in IE it’s not 40px to far on the left side of the page.
Any ideas? Sorry, I’m really new to this!
Hi All,
PROBLEM SOLVED!!!!
I used this solution below and now all works on ALL Browsers!!!
http://code.google.com/p/ie7-js/
Check that out and that should help!
Thanks again for an awesome navigation bar solution!!!
I’m completely and totally confused on the -40px thing. I’m using Expression Web 2 and IE 8 to develop and proof my site, and using a horizontal nav bar (thank you, Matt!!). I’ve tried the solution above, but it doesn’t seem to work for me. The following is just under my title, and I have the referenced files where they should be:
Yet, when I check the page in IE8, the nav bar is sitting to the right by 40 px. When I turn on compatibility view, it slides back where it should.
Any help would be MUCH appreciated!
Looks like wordpress doesn’t like the code I tried to paste.
The code I have on my page can be found at this address: http://www.charlescooke.me.uk/web/lab_notes/ie7_script.html
Code sample 5.
Thanks again!
I need help,
I tried this and so far it’s been going well
until this happened…
http://pinmeupthewall.com/dyellene/
as you can see as you hover, there’s still a bit left
how do I get rid of it and what do you suggest?
Thanks.
Can I use the CSS in wordpress? Prob a lame question but I am new to this and want to add a menu with images and your generator seems perfect. I have the files on my computer. I put the jpg in my images folder for the theme. But how do I get the menu working on my page? Where do I put the CSS file? Thank you so much!
I’m having exactly the same issue of it being nudged c. 40px to the right. I’m wondering – where does this number come from? I’ve built the navbar manually, not using the generator – it must be somewhere within how I’ve put it together, right?
Matt
Is there a way to have a dropdown menu with rollovers images from the rollover nav bar?