100% CSS Rollovers

This is one of my favorite little tricks I’ve managed to wrangle over the years of googling “css rollover.” It became a full proof thing when I figured out how ma.tt had done his rollovers on an older version of his site. Really though it isn’t rocket science (by any means) and anybody with moderate understanding of CSS and XHTML should have no problems figuring it out if they haven’t already.

I prefer doing it this way because it uses a plain unordered list so if something breaks they will always have the navigation in a plain unordered list. You also don’t have to do any ghetto stuff like use a transparent .gif as a place holder or use a sneaky span tag to have some sort of content associated to the button link (janky)… and it doesn’t need any javascript.

I use this method of making main navigation menus pretty when it’s a hand-coded website or when it’s a CMS with a fixed navigation. By fixed navigation I mean the client won’t be trying to change the main navigation all the time. Since every button needs an image with two or three states it can become a pain if the client keeps changing their mind.

So for starters you need a plain unordered list with some id’s for later on when styling the CSS. Every list item houses a link as a button is no good if it doesn’t link anywhere.

<ul id="nav">
<li id="one"><a href="#">one</a></li>
<li id="two"><a href="#">two</a></li>
</ul>

I created two buttons of equal width, this also works with various widths just be sure to add the width to the specific id. I use the sliding door method so each image has two button states (link and hover), if you were feeling slick you could add a third button for the active state to the same image. This avoids that annoying flicker upon hover when you haven’t cached the hover images yet because the hover is attached to the image that loads first.

Obviously you must be careful to align the buttons on the image so they don’t look like they jump when you hover. If your button is 25px tall the image must be 50px tall for two states and 75px if adding an active state. In my example here the images are 75px x 25px. Here are the buttons:

one two

Next is the CSS:

#nav li {display:inline;margin:0;padding:0;}
#one, #two {float:left;}
#one a, #two a {display:block;height:25px;text-indent:-9999px;width:75px;}
#one {background:url(one.png) no-repeat 0 0;}
#one:hover {background:url(one.png) no-repeat 0 -25px;}
#two {background:url(two.png) no-repeat 0 0;}
#two:hover {background:url(two.png) no-repeat 0 -25px;}

It’s all pretty basic and can be expanded upon to suit your needs (ie: kill the float:left and they stack on top of each other or position them absolutely). All it requires is a bit of math but it’s easy, just be sure your button size is reflected in the hover state background position (-25px in above example) Here is a break down line by line of the above:

  • #nav li {display:inline;margin:0;padding:0;} removes the bullets from the unordered list.
  • #one, #two {float:left;} makes the list items float left so they sit next to each other in a row.
  • #one {background:url(one.png) no-repeat 0 0;} and #two {background:url(two.png) no-repeat 0 0;} are the regular link states with their background positions at 0.
  • #one:hover {background:url(one.png) no-repeat 0 -25px;} and #two:hover {background:url(two.png) no-repeat 0 -25px;} are the hover states with the top background position to set to -25px, this number is the height of your button.

Here is a demo page with it all working in case my writing is pure gibberish and you find it easier to see it and take it apart. View the demo page.

I also compiled a zip archive in case you are as lazy as I am. Download zip archive.

Also I’m done with ie6 so if it works great if it doesn’t I’m sure you will figure it out 🙂