Talk to me about anything. If you’d like to work with me, or
even if you just need a hug, I’ll get back to you shortly.

Please enter your name

Please enter a valid e-mail

It's cold!

Say something!

Super Fantastic CSS Navigation Image Rollovers

The fun part of CSS (if you’re a weirdo like me and get a kick out of this sort of thing) is coming up with the most optimized, cleanest, accessible, and compliant code that you possibly can. This tutorial will show you one of my favorite ways of doing a navigation menu with image rollovers done in CSS that uses only one image and very minimal HTML / CSS code. This is by no means the only way of going about it, nor is it the “right” way if there is such a thing, but I’ve found this to be a very quick and efficient way of accomplishing our task.

This article is the first of a 2 part series, and the second half will apply this tutorial into creating a CSS only dropdown menu navigation with the image rollovers that is compliant with IE6 and up.

Click here to see a demo of what we’ll be doing.

The first trick is to make your navigation image. The best way of going about this is to create your menu in photoshop, double it’s width (or height if you are doing a horizontal navigation), and then paste the exact same thing with ever link in its rollover state right next to it. It should look something like this. This makes for quicker load time than if you did every image separately and even less CSS needed.

Next we will write all of the HTML out:
<ul id="navigation">
    <li><a href="index.php" class="link1">Home</a></li>
    <li><a href="metal" class="link2">Metal</a></li>
    <li><a href="plastic" class="link3">Plastic</a></li>
    <li><a href="services.php" class="link4">Services</a></li>
    <li><a href="news.php" class="link5">News</a></li>
    <li><a href="catalog.php" class="link6">Catalog</a></li>
    <li><a href="about.php" class="link7">About Us</a></li>
    <li><a href="contact.php" class="link8">Contact</a></li>
    <li><a href="users.php" class="link9">Registered Users</a></li>

I always set up my navigation menus in unordered lists. Normally just one ‘id’ on the ‘ul’ tag would be enough HTML, but in the case of each link having its own background then each link has to have its own class.

Here is the CSS for our menu:
#navigation {
	border-right:1px solid #999;
	padding:10px 0px;
#navigation a  {
#navigation a.link1:hover {background-position:-146px 0px;}
#navigation a.link2 {background-position:0px -47px;}
#navigation a.link2:hover {background-position:-146px -47px;}
#navigation a.link3 {background-position:0px -94px;}
#navigation a.link3:hover{background-position:-146px -94px;}
#navigation a.link4 {background-position:0px -141px;}
#navigation a.link4:hover {background-position:-146px -141px;}
#navigation a.link5 {background-position:0px -188px;}
#navigation a.link5:hover {background-position:-146px -188px;}
#navigation a.link6 {background-position:0px -235px;}
#navigation a.link6:hover {background-position:-146px -235px;}
#navigation a.link7 {background-position:0px -282px;}
#navigation a.link7:hover {background-position:-146px -282px;}
#navigation a.link8 {background-position:0px -329px;}
#navigation a.link8:hover {background-position:-146px -329px;}
#navigation a.link9 {background-position:0px -375px; height:65px;}
#navigation a.link9:hover {background-position:-146px -375px;}

Now for the broken down detailed explanation of the CSS:
  • The border and padding on the #navigation is simply for looks on this menu
  • The width on #navigation is set to the size of our whole nav menu
  • #navigation a lets us apply the following styles to every link within the ul
  • Display:block is an extremely useful property in many situations. It will change the element into a block level element, i.e. it will act like a div. We can now apply styles to a link that we couldn’t have before.
  • Background:url(navigation.png) sets the background for each link
  • The height is important, otherwise the link will only be the size of the text by default. In this case, the links’ width is determined by the containing ul’s width.
  • Text-indent:-9000px moves the text within the anchor tag off of the page which allows search engines to still have something to index
  • Lastly, the key to this CSS strategy is changing the background-position separately for every link and its hover state. For example, #navigation a.link3:hover{background-position:-146px -94px;} tells the browser to move the background image on our 3rd link’s hover state 146 pixels to the left and 94 pixels up. These numbers are all determined by the size of each link, e.g. each link’s background position is 47 pixels higher than the one before it because that is the height of our links.

That’s it! Probably the trickiest part is setting up your image and getting the pixels right on the background positions. If you have any suggestions, comments or questions, please leave them! If you stumbled upon this little gem, make you check out CSS Navigation Rollovers With Drop Downs where we use this rollover technique in a tutorial to create CSS drop downs.

  1. Tom says:

    Site is looking slick buddy. Totally subscribing to your RSS feed. Also twittering it.

  2. rolf says:

    im jst posting to see that weird post bg effect…
    tis cool

  3. John says:

    This is just what i am looking for. But my Nav is More Vert then Horz I can not figure out how to make it work for me in that way.

    • Joren Rapini says:


      I’m assuming you meant your navigation was horizontal, not vertical? Because the demo here shows a vertical navigation. My best advice is for you to take a look at how I did the navigation on this website with Firebug (tool has a million uses for learning how others did their CSS). All you really need to do is make sure that each item has a width, and then float all the li’s to the left and they will bump up against each other horizontally.

  4. Charlotte says:

    This is a cool tutorial.
    I may use this for some of my future projects.

    Keep it up.

  5. Nelce says:

    Hi Joren
    Thanks for a cool tutorial. I used it for the navigation of this site and it actually links to the pages, but the navigation image does not display. I am not sure what I am doing wrong. I am not really experienced with this so I am not sure where to look for my error. Thanks again.

    • Joren Rapini says:

      Under ‘#navigation a’ you specify its background as url(navigation.png). Navigation.png does not exist, at least not in the same folder as your CSS file, so you have to point it to the background image correctly. So, say you have your CSS file in a CSS folder, and the image in an Images folder, and they’re both in your document root, then it should be something like url(../images/navigation.png). Make sense?

  6. Nelce says:

    Thank you!!!! I’m an idiot! Fixed it, and it works perfectly. Thanks for responding so quickly. Awesome site!

  7. Brian says:

    Hi Joren,

    This is exactly what I was looking for, and works like a charm for me in Firefox! But…it’s misaligned in Internet Explorer. I can’t figure out what’s wrong. Any ideas? Here’s my site & code:


    Wine Bar

    padding: 0 0 10px 0;
    list-style-type: none;
    /*border: 1px solid #ff6600;
    background: url(“images/black80.png”) repeat fixed;
    background-position: top left;
    background-position: auto;
    background-overflow: hidden;*/
    #navmenu a{
    float: left;
    background: url(“images/BSHeader_bottom.png”) no-repeat;
    height: 25px;
    text-indent: -9000px;
    #navmenu a.link1 {
    background-position: 0px 0px;
    width: 186px;
    #navmenu a.link1:hover {
    background-position: 0px -31px;
    width: 186px;
    #navmenu a.link2 {
    background-position: -186px 0px;
    width: 409px;
    #navmenu a.link2:hover {
    background-position: -186px -31px;
    width: 409px;
    #navmenu a.link3 {
    background-position: -595px 0px;
    width: 199px;
    #navmenu a.link3:hover {
    background-position: -595px -31px;
    width: 199px;
    #navmenu a.link4 {
    background-position: -794px 0px;
    width: 196px;
    #navmenu a.link4:hover {
    background-position: -794px -31px;
    width: 196px;

    Thanks in advance for your help!

    • Joren Rapini says:

      Hmm, try floating the list items to the left instead of the anchors, and give the anchors display:block;. And make sure that all the anchors do not add up to a width larger than your container and you should be alright.

      • Brian says:

        You’re my boy, Joren! I added “#navmenu li{float: left;}” and that did it! Thank you so much for this. I think I’m ready to launch.

        For a future enhancement, do you have any suggestions for how to make the current nav image remain highlighted when it’s not hovered?

        Thanks again!

      • Joren Rapini says:

        You mean change the background image to the rollover state of whatever page the user is currently on?

      • Joren Rapini says:

        Well, if you’re using a template system and can’t modify the navigation’s HTML for each separate page, then you’ll have to create a javascript function that changes the background position depending on what page the user is on, and load that function with a different parameter for each page. This can be accomplished pretty easily with jQuery.

      • Brian says:

        OK, great. I will look into that sometime in the future. Again – thanks for your help. Great site!

  8. Barry says:

    Hi Joe,

    Thanks very much for your tutorial. I followed it and achieved the menu on but I am having issues with the positioninig. Please can you help me out.

    Thanks very much

    • Joren Rapini says:

      Heh, I have no idea where this Joe comes from. . . your not the first person to do that. Anyways, you’ll have to be more descriptive, I don’t know what you’re trying to achieve on that link.

      • Barry says:

        Ok sorry Joren, I followed your navigation example and got that result, I still can’t figure out where the problem is with my scripts. Please can you help me.

      • Joren Rapini says:

        Barry, I don’t know what the problem is, so if you want me to help you fix it, you have to actually tell me what it is that’s wrong.

  9. Barry says:

    The problem with the navigation is that it’s suppose to have same height with the animation div. but i don’t know exactly what i am doing wrong. It hangs in between the both thereby not looking nice.

    Thanks for your help. if you require the source code, you can view it.

  10. Andy says:

    Hi Joren,

    Like your work here, Is it possible to add an active state to this, so when in a page it stays the same to show you are on that page.

    Thanks for any advise Andy.

    • Joren Rapini says:

      Thanks! Yes, all you would need to do is make room in the sprite image for a third row of navigation, and then just add a class to the specific link that its state changes on each page, then just give that active class new background-position properties.

      However, if you have the links coming through on an include or dynamic and you can’t manually add a class for each page, then you could add the class via a javascript function which is what I normally do.

  11. Kat says:

    I tried the text-indent: -9000px so that the link text does not show up except to search engines. However, the text is still showing up.

    Note that I am aware that Im doing a horizontal menu, rather than the vertical way you are showing in this example. Im just trying to figure out what I need to do in this case to get the text to leave the confines of the navigation box.

    URL is here: (link is not quite work-safe)

    • Joren Rapini says:

      Hey Kat, I took a look at your link briefly with Firebug, and I don’t see any text indent style being applied to any of the links. Try #navigation a {text-indent:-9000px} in your style sheet.

      • Kat says:

        Its there now in #navigation a but yeah, the text still remains there. I tried this in firefox too.

      • Joren Rapini says:

        The browser is probably forcing the text to stay, because if you indent the text off the page then the links will be non-existent. By default, links are inline style elements. You are applying a height of 40px but that means nothing unless you change its display type to something like display:block.

  12. Kat says:

    Of course, if I apply display: block to “#navigation a”, it will show the full navigation image since Im doing a horizontal menu vs a vertical one (or at least, this is my guess). I tried applying it to the #navigation, but that put me back in the original problem. :/

    • Joren Rapini says:

      Yup, if you’re using background images, you’ll have to specify a width for each link. There is no other way when using images. Horizontals are a little more tedious because each link is typically going to have a different width, as opposed to vertical navs where all links have the same width, so less CSS.

      • Kat says:

        So would I need to specify the width of both a, and a:hover regarding each seperate link? how would that keep the navigation image from showing up in areas below like you just saw?

      • Joren Rapini says:

        If you want any block level elements to bump up against each other instead of dropping down below, you need to use float:left. If you haven’t had any experience with this before then I suggest looking up some tutorials on it or just playing around with it as much as possible. Read up on display types as well, all of this will be explained.

  13. Kat says:

    Thank you for your patience. I got it working. I just hope I can get a spacer to add some blank menu real estate between “Contact” and “Current Menu”. I tried inserting a list item to server as a spacer I can easily control the spacing distance with but that might not be the best guess. :)

  14. Brian says:

    Hi Joren,

    This is a fantastic tutorial, which I’ve used before with great success! I’m working on a new project and am having difficulty executing in IE. I’ve amended your code slightly by applying an HTML “body” tag on each site page, then referencing that in the CSS so that the current page stays highlighted (same as hover).

    What I have so far works perfectly in Firefox and Safari, but the navmenu button for any given “current” page stays hidden in IE. I’ve tried commenting-out the “current” and “hover” code in my CSS, but it’s the same result.

    Any insight would be greatly appreciated!



    #navmenu ul li a{
    margin: 0;
    padding: 0;
    font-family: “Arial”, “Verdana”, “Trebuchet MS”, sans-serif;
    font-size: 14px;
    color: #fff;

    #navmenu ul li a:hover{
    color: #ddd;

    #navmenu ul{
    list-style-type: none;
    margin: 0;
    padding: 0;

    #navmenu li a{
    text-indent: -9000px;

    width: 100%;
    padding: 0;
    list-style-type: none;
    float: left;
    display: block;

    #navmenu li{
    float: left;

    .ie #navmenu li{
    float: left;

    #navmenu a{
    display: block;
    background: url(“images/header.gif”) no-repeat;
    height: 101px;
    text-indent: -9000px;

    #navmenu a#home {
    background-position: 0px 0px ;
    width: 370px;

    body#home a#home, #navmenu a#home:hover {
    background-position: 0px -101px ;
    width: 370px;

    #navmenu a#about {
    background-position: -370px 0px;
    width: 170px;

    body#about a#about, #navmenu a#about:hover {
    background-position: -370px -101px;
    width: 170px;

    #navmenu a#wines {
    background-position: -540px 0px;
    width: 170px;

    body#wines a#wines, #navmenu a#wines:hover {
    background-position: -540px -101px;
    width: 170px;

    #navmenu a#purchase {
    background-position: -710px 0px;
    width: 280px;

    body#blog a#purchase, #navmenu a#purchase:hover {
    background-position: -710px -101px;
    width: 280px;

    • Joren Rapini says:

      Hey Brian, I can never stress this enough to front end developers. Always validate your HTML/CSS, especially if you’re running into any problems. I would guess that the fact the id HOME is being used twice is what’s causing your problem.

      • Brian says:

        Joren…You are a freaking saint, man! I updated the li id’s from “home” (which is the same id as the body id) to “nav-home”. Then I updated those same id’s in my CSS…and presto! I’m still learning a lot, and it’s especially thanks to blogs like yours. Thanks again, man!

  15. Richard says:

    Any sample of horizontal menu, because i don’t get it.

  16. Chris says:


    I’m trying out your tutorial and running into a couple of issues. I’m trying to have the menu’s change on every page to reflect the page they are on and also have a space above the first and last links, i’m not sure what causing problems.

    On the index page,
    the hover effects work fine, to get the space to extra space from the image to show up above and below the only thing i can figure out to do is add a link and remove hover from html but this, of course leave a blank link.

    When I generate nav on other pages above issue is still there and I can’t figure out how to get the hover effect to happen on the first link (which is the second link since the “first” one is a “dummy”. Here’s a link to this page.

    Hope you can help or can suggest an easier way of achieving rollover effect.


  17. Warren Flaks says:

    That was very interesting. There are not a lot of blogs out there with good information on this topic. I hope to read more good comments when I come back in a few days. Thank you for the information.

  18. Steve says:

    Great tutorial, and one of the best ones I have tried to follow. Now I have modified this a bit to work with a site I am doing, and while I have it working, I had a question if anyone has time.

    Now you use one big image and move it all around, I am using 1 image per link/nav placement is one of my modifications. Now in IE (and in my visual editor) I see gaps between a few of the blocks/link, very slight. In yours all the blocks are right up against each other. It seems to be links 3-5, as when I put in overflow: auto on the li tag, they all fix themselves, but then I see a scroll bar when in a browser. If I remove the heights, I see the image repeating in some of the spaces. I must be over looking something?

    Thanks in advance!

  19. Vee says:

    YOU ARE AWESOME! Thank you so much. I’ve been having areal hard time at my web development class and this is the only tutorial I actually understood. I just wanted to share my appreciation :D

  20. john says:

    great tut; Had troubles with the couldnt remove bullets so switched to divs & spans it works perfect

  21. Brien says:


    This is a fantastic technique! I only have one question: My navigation.png is 400 x 299, with 7 links on it. Each button is 200 x 42. I can’t for the life of me figure out the positioning. Got any tips on how to solve this?

  22. Leo the Yardie Chick says:

    Hello, Joren! I found your tutorial and it works great regarding the rollover part, but something’s wrong when I’m using it on my menu. It’s supposed to show seven menu options, but it’s only showing the first option’s image for all seven. O_O

    It’ll make more sense visually, because even describing it is confusing me right now. ^^; I’ve included the link to my menu image:, and to the modified menu code:

    This has been bugging me since Wednesday, and I’m at my wits end trying to figure it out. I’ve even had the code validated, and it passed…so I’m not sure what’s wrong. :(

    Help, please?

  23. Sandeep says:

    Awesome post!

  24. Does this menu bar use flash? And will people using a Mac be able to see it?

  25. Wow, awesome blog layout! How lengthy have you been running a blog for? you made running a blog glance easy. The entire look of your site is magnificent, as smartly as the content!

  26. Wow nice tutorial and it worked great too. Thank you very much.

  27. Arbaz says:

    Is this internal CSS or externally attached?

  28. Nicky says:

    thanks I need people like you.

  29. Anshul says:

    Its really worked and thanx for this Demo…

  30. Smart work man, you really rocked. You place nice content. The main point is that it really worked too..

  31. Nimesh Kumar says:

    can i have navigation.png background ..

  32. Apa says:

    Great tutorial, but it would be better if background.png was given…

  33. Dragos says:

    this post is awesome! as a html beginner I found very useful this post! thanks a lot!
    But please, help me to understand how to do a sub-menu of this on the right of the mail menu? Did I must do a new background image for the menu?
    Please help me to understand.

  34. [...] Super Fantastic CSS Navigation Image Rollovers [...]

  35. [...] Super Fantastic CSS Navigation Image Rollovers – A quick and very optimized way of creating your navigation’s mouse overs using just one image and CSS. [...]

  36. [...] Menu with CSS and Improve it with jQuery Easy CSS Dropdown Menus Designing the Digg Header Super Fantastic CSS Navigation Image Rollovers CSS Navigation Rollovers with Drop-downs Elegant Glass-Style Navigation Bar Using CSS and Toggle [...]

  37. [...] read Super Fantastic CSS Navigation Image Rollovers, then come back to this tutorial and learn how to code your images into working CSS [...]

  38. [...] Super Fantastic CSS Navigation Image Rollovers [...]

  39. [...] 26. Super Fantastic Css Navigation Image Rollovers [...]

  40. [...] Демо | Страница с описанием [...]

  41. [...] Super Fantastic Css Navigation Image Rollovers [...]

  42. [...] 79. Super Fantastic CSS Navigation Image Rollovers [...]

  43. [...] 79. Super Fantastic CSS Navigation Image Rollovers [...]

  44. [...] 79. Super Fantastic CSS Navigation Image Rollovers [...]


  46. [...] 79. Super Fantastic CSS Navigation Image Rollovers [...]


  48. [...] Super Fantastic CSS Navigation Image Rollovers | The Blog of Jor [...]

  49. […] 79. Super Fantastic CSS Navigation Image Rollovers […]

  50. […] 79. Super Fantastic CSS Navigation Image Rollovers […]

  51. […] 79. Super Fantastic CSS Navigation Image Rollovers […]

  52. […] 79. Super Fantastic CSS Navigation Image Rollovers […]

  53. […] 79. Super Fantastic CSS Navigation Image Rollovers […]

Leave a Reply

This site is protected by Comment SPAM Wiper.