Image rollovers without JavaScript!
I don’t like JavaScript. It’s clunky, it’s outside of my typical workflow and it tries to get up in HTML’s business when it should mind its own. So, when I found a way to solve a common website development issue that typically requires JavaScript without using any JavaScript, I jumped at the chance to try it out.
The problem space I’m talking about is rollover images. The idea is fairly simple, you have a base image and, using JavaScript you tell the browser to switch the source of that image to a different image file when the mouse rolls over the base image. Simple enough, but there are some downsides to this. For one, you have to have two different source images, one for the normal state and a second for the rollover state. This means that the browser has to load those two images each time the page containing the rollover is loaded.
This is bad for several reasons. For one you must preload the “alternate state” images, which means that you not only have to have a JavaScript function to swap the images but now you have to have a function to preload all of the needed images so there’s no delay when the mouse is moved over the rollover image.
But there is a simpler way…
Cascading Style Sheets (CSS) are a big deal in the web development world. They’re changing the way things are being done and I very regularly find ways to do things with CSS that I previously accomplished in other, far-less-simple ways. The complex, and sometimes confusing task of image slicing and dicing (and the necessary JavaScript) have given way to the power of CSS.
The idea is simple, rather than having two or more image files that are called when needed, you have one “master” image which contains all of the rollover, active or visited states on one image. Then, rather than cutting those into individual images and using JavaScript to decide when each image should be loaded, you use the power of CSS to cause the images to change.
If you’ve used CSS for rollovers before you’ve probably done something like this:
...
background: url("button.gif") top left no-repeat;
}
#menu a:hover {
...
background-image: url("button-over.gif");
}
#menu a:active {
...
background-image: url("button-active.gif");
}
/* etc... */
If you’re using one common image there’s no need to change the background image. We just change the position of the background image by moving it a certain number of pixels. So, the resulting CSS would be more like this:
background: url("button.gif") 0 0 no-repeat;
...
}
#menu a:hover {
background-position: -157px 0;
...
}
#menu a:active {
background-position: -314px 0;
...
}
Below is an example “master” image.

And here is a working example of a rollover effect using the master image.
Now, if we can just find ways to solve other problems using CSS instead of JavaScript we’ll be in good shape!
11 Responses to “Image rollovers without JavaScript!”
Leave a Reply
The opinions expressed by individuals posting in the Summersault Blog are not necessarily those of Summersault, LLC. While we try to insure the quality and accuracy of the information presented here, we make no guarantees about its suitability for any particular purpose.


March 29th, 2005 at 12:55 pm
It looks like you gave two different rollover options with CSS.
Is the second one “better” because it’s easier to manage one image with 3 different panels than to manage 3 variations of the same image, in 3 different files?
Or is there another technical reason the second option is better?
March 29th, 2005 at 1:21 pm
The first CSS rollover option is one that is basically the same in theory as using JavaScript. The second, as you stated, only uses one image, which is much easier to manage.
As far as a technical reason for why the second option is “better”, I believe the main reason is because you’re only referencing one image file instead of two or more. Another technical issue fixed by using one master image instead of two or more is that there’s no delay when you rollover using the 2nd option. With the first option the image isn’t loaded until you move over the link, which can produce a delay on slower connections.
April 11th, 2005 at 4:55 am
Using background: url(”x.gif”) is a very slow solution as you can see the menu from my homepage. Is a way to force the browser to cache the used images ?
April 18th, 2005 at 6:50 pm
I like the second option. but it does not seem to work in Gecko browsers…
April 25th, 2005 at 2:53 pm
I’ve tested this code on Mozilla 1.0 and several versions of Netscape and IE and it seems to be fine. Please feel free to send me any browser/version information if you find a browser that this CSS doesn’t work with.
May 17th, 2005 at 3:43 am
I dont think Safari on the mac supports the background CSS.
December 1st, 2005 at 3:06 pm
It works perfectly under Mac os X with Safari 2.0.2, IE 5.2.3, FireFox 1.0.6, Netscape 7.2, Shiira 0.9.5 and Opera 7.54 as well as under Windows XP pro with Netscape 7.2, FireFox 0.9.3 & 1.5, and IE 6.0.26.
December 8th, 2005 at 8:00 am
I used it in Netscape 8.0.4 and Firefox 1.0.7 but de red image doesn’t stay when i clicked it, it returns to white with a border around the image.
On InternetExplorer 6 it works fine.
Is there a workaround for the other two browsers?
August 25th, 2006 at 11:47 am
When you preload the images it doesn’t take as long… but thanks for the idea. I like it a lot.
August 25th, 2006 at 11:50 am
Yes, pre-loading is a good idea, just as it is with traditional Javascript-fueled rollovers.
September 7th, 2006 at 12:37 pm
Actually, option two seems very preferable. If you go to seeunity.com - you’ll see that the top nav uses the first method - but the first time you rollover - you’ll get some funky experiences. I am guessing that this second method will work better.