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>
</ul>

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;
	width:145px;
}
#navigation a  {
	display:block;
	background:url(navigation.png);
	height:47px;
	text-indent:-9000px;
}
#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.

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

    December 5, 2008 at 2:18 pm
    Reply

  2. rolf

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

    January 16, 2009 at 9:17 pm
    Reply

  3. 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.

    June 4, 2009 at 12:47 pm
    Reply

    • John,

      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.

      June 4, 2009 at 1:28 pm
      Reply

      • I got it to work.
        http://trapdoorinteractive.com/newwebsite/index.html
        Not done yet but your code help a bunch

        June 5, 2009 at 8:55 pm

      • Glad I could help. First thing I noticed when I looked at your navigation: you should be using PNG’s for that kind of an image, not a JPG. PNG’s are good especially for vector elements like text, and things that don’t have a ton of different colors in them. You’ll get a smaller file size and you won’t see the lossy effect around the text like you get with a compressed JPG.

        June 6, 2009 at 11:54 am

      • ok awsome

        June 7, 2009 at 4:01 pm

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

    Keep it up.

    July 2, 2009 at 12:08 pm
    Reply

  5. 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.

    October 16, 2009 at 4:34 pm
    Reply

    • 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?

      October 16, 2009 at 8:55 pm
      Reply

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

    October 17, 2009 at 5:41 am
    Reply

  7. 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:

    http://www.blueskyhigh.com/

    HTML

    Home
    Blog
    Wine Bar
    About

    CSS
    #navmenu{
    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!

    December 15, 2009 at 1:27 am
    Reply

    • 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.

      December 15, 2009 at 7:50 am
      Reply

      • 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!

        December 16, 2009 at 12:45 am

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

        December 16, 2009 at 10:55 am

      • Exactly!

        December 16, 2009 at 2:35 pm

      • 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.

        December 16, 2009 at 2:42 pm

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

        December 16, 2009 at 8:35 pm

  8. Hi Joe,

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

    Thanks very much

    December 23, 2009 at 1:27 am
    Reply

    • 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.

      December 23, 2009 at 10:55 am
      Reply

      • 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.

        December 25, 2009 at 12:40 pm

      • 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.

        December 25, 2009 at 10:55 pm

  9. 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.

    December 26, 2009 at 5:36 am
    Reply

  10. Andy

    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.

    February 7, 2010 at 9:00 am
    Reply

    • 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.

      February 7, 2010 at 11:13 am
      Reply

  11. [...] CSS Navigation Image Rollovers [...]

    June 8, 2009 at 9:15 am
    Reply

  12. [...] CSS Navigation Image Rollovers [...]

    June 8, 2009 at 9:15 am
    Reply

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

    June 12, 2009 at 10:26 pm
    Reply

  14. [...] CSS Navigation Image Rollovers [...]

    August 8, 2009 at 4:56 pm
    Reply

  15. [...] 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. [...]

    December 17, 2009 at 11:18 am
    Reply

Leave a Reply