Although we thought this problem had been perfected years ago, we still manage to come across professional, high-trafficked websites using broken and outdated CSS image rollover techniques. This is absolutely unacceptable and unnecessary.
Designers and developers are still using CSS image rollovers that are guilty of one or more of the following:
- use JavaScript
- not accessible to mobile browsers, screen readers, etc
- produce a flicker effect upon the initial rollover
- use multiple images
There is a way to produce JavaScript-free, accessible, flicker-free, single-image CSS image rollovers. Here’s how:
The Image
As mentioned above, we’re only using one image in this tutorial. None of that multi-image CSS image rollover nonsense. Less is more here.
The image to the right is what we’ll be working with in this tutorial. Before we continue, let me explain the idea behind this single-image technique.
How it works
What we’re essentially doing here is stacking each link property’s image on top of each other. By doing this, we can use the CSS background-position property to shift the background position of the image depending on the current state of the link.
By using a single image and switching the background-position, we eliminate any image loading flicker which occurs in other CSS image rollover tutorials. Why? Easy. Unless you run JavaScript to preload the additional images (which is unnecessary), the browser won’t actually load the background images of the additional properties (:visited, :hover, :active) until those states are triggered. For example: the a:hover property’s background image will not be loaded until the user rolls over its link. However, using a single-image technique, the browser loads the entire image, and we simply shift between different background-positions. Make sense?
Image information
The image we’re using in this tutorial has the link properties stacked in the following order: a:link, a:visited, a:hover, a:active. Each property (link state) has a height of approximately 50px. It is important that the height of each segment is exactly the same, and that they are stacked on top of each other. This will avoid any “jumping” issues which could otherwise occur if there is any additional space in between the segments. The total height of the image is 200px (4×50px = 200px). This is just an example, though, and you can make the segments as wide or tall as you’d like.
The XHTML
The XHTML for a CSS image rollover looks very similar to standard hyperlink markup. The only addition that will more than likely need to be made is assigning a class or an id to the link. If you have multiple CSS image rollovers throughout your website, then using a class or an id will give you the ability to target the specific set of links (using a class) or single link (using an id) with ease in your CSS style sheet.
View page information »
As I said, the only difference between a CSS image rollover link and a standard hyperlink is the addition of the class element. In some cases, you may already be using a class or an id in your XHTML, and therefore, there would be no difference whatsoever.
The CSS
Rather than show you how to create a basic CSS image rollover with a link (a:link) and a hover (a:hover) property, we’re going to show you how to make use of the visited (a:visited) and active (a:active) properties, too.
First, we define the properties for the a.singleRollover selector. The width of this selector must be the same as the width of the image, and the height must be equivalent to the height of one of the segments of the image (or one of the link states – 50px). As you can see, the background-position is at 0,0 - the very top of the image. This will display the a:link background image.
Next, we define the background-position for the other three states of the a.singleRollover selector. These background-positions will display the additional segments within the image, depending on the state of the link.
/** Declaration for the a.singleRollover selector **/
a.singleRollover {
display: block;
width: 50px;
height: 50px;
background: url(images/singleRolloverImage.jpg) no-repeat 0 0;
}
/** Declaration for the additional states of the a.singleRollover selector **/
a:visited.singleRollover {
background-position: 0 -50px;
}
a:hover.singleRollover {
background-position: 0 -100px;
}
a:active.singleRollover {
background-position: 0 -150px;
}
Accessibility
As you can see, the image rollover has one problem: the alt text is being output on top of the CSS image rollover. What should we do? We certainly don’t want to eliminate the alt text – no, that would make this rollover inaccessible (not to mention that’s just sloppy coding).
The solution
By adding some additional properties to our a.singleRollover selector, we can hide the text that is currently floating over our CSS image rollover.
a.singleRollover {
display: block;
width: 50px;
height: 50px;
background: url(images/singleRolloverImage.jpg) no-repeat 0 0;
overflow: hidden;
text-indent: -10000px;
font-size: 0px;
line-height: 0px;
}
And that’s all there is to it. You now have an accessible, standard compliant, flicker-free, single-image CSS image rollover! If you have anything else to add to make this better, please leave a comment below and we’ll add it to the tutorial.


Why not just link to the original (and more in-depth) CSS Sprites article?
Good question, Andrew. We felt that the article may be a little difficult to comprehend for CSS newcomers. In addition, the CSS Sprites article which you have referenced teaches you how to create image rollovers using multiple list elements. What if someone just wants to have a single rollover and not use lists? For this reason, there is considerably less markup involved in our example. In addition, we tackle the accessibility issue within this article, unlike the CSS Sprites article which directs you to other websites.
You could also use “display: block;” instead of the ‘text filling’ and offsetting if you don’t mind the empty link.
Yes, this is how we used to do it, however, that is inaccessible, outdated, and unnecessary. What about mobile users who don’t see the design of the website, and therefore, don’t see the link?
Yeah I thought so..
.
Still, I like this combined image method myself, great article. It annoys me too to see all those sites with ‘lagging’ rollovers ‘in the 21st century’
What are the SEO implications of using this method with text being out of view?
David, great question. Just like anything else with SEO, as long as you’re not abusing the tactic, you’re going to be okay. Also, don’t keyword stuff on your image replacements. Make sure that the text is relevant to the image.
This is just so smart! A brilliantly cunning technique – quite the most inventive I’ve come across in ten years of using image rollovers! Wins hands-down over the CSS Sprites list technique.
Thanks John! Yes, we think it’s the better alternative, too. The least amount of markup and the most accessible.
Thanks for putting this together, straight-forward, plus the accessibility aspect saved me some additional research time!
This is a great article and its been a great help for me designing a new menu. I do have one issue though. When you turn off css the menu displays fine, without any problems. When you turn off images, you are presented with no navigation. As yet I haven’t been able to find a solution to this. But thanks for the great start.
Tom, glad you’ve found this article useful.
Even when you turn off images in a web browser, the background images will still load since they are being called through the external CSS stylesheet. If someone turns off the stylesheet, then the menu text links will show, so this should work just fine no matter what the user decides to do.
Hey Matt,
thanks for the reply, i’ve looked at the demo in FF3, using web developer tool bar to turn off images and there is no text displaying, if you turn off images off in IE7 there is still no text displaying. The link is still there but you can’t see it. I did find this tutorial: http://ryanroberts.co.uk/_dev/experiments/accessible-rollovers/index.html and am trying to figure it out.
Wow, it’s a really simple solution, each day I’m even more impressed about what xhtml and css can do without javascript’s help (since I try to avoid flash for SEO, javascript has been my company for a long time).
Great article, i’ll have no option but bookmark it.
Hello. Your article was very helpful. I’m fairly new to HTML and CSS. Your suggestion of using the single CSS rollover makes sense, although I have text that I want to stand as text. How can I make this single rollover work and still be able to use text? I’m not sure if this was touched upon in this article or not.
Thanks this would really help with a site I’m coding.
Jennifer, if you want a text rollover, surely you could simply use the :hover pseudo-class?