Back to CHROMATIC's Blog Home Page

Over the years, there have been several methods used to create CSS image rollovers. Accept no substitutes: this is the best way to do it.

CSS Image Rollovers: Accessible, Standard Compliant, Flicker-Free Image
Delicious Save to Delicious

CSS Image Rollovers: Accessible, Standard Compliant, Flicker-Free

Matt | Sunday, February 8th, 2009 16 comments

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:

View Demo »

The Image

CSS Rollover Single ImageAs 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

View page information »

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

View page information »

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.

Demo this Tutorial » | Download Demo » | Learn CSS »

About the Author...

Matt is the Director of Operations at CHROMATIC. He is really intrigued by all aspects of the web, business, and everything in between. Matt has been told that he has a sometimes unhealthy passion for going above and beyond to over-deliver for clients. That's just who he is, though. He's big on Macs, music, the outdoors, and long, spontaneous road trips.

Like this post? What next?
Comments for this postComments are directly below (arrow image)

Leave a Comment

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

  2. 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’ :P .

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

  4. JohnMiller February 27, 2009

    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.

  5. Thanks for putting this together, straight-forward, plus the accessibility aspect saved me some additional research time!

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

  7. Cesar Castro July 16, 2009

    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.

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

    • JohnMiller January 27, 2010

      Jennifer, if you want a text rollover, surely you could simply use the :hover pseudo-class?

Leave a comment for this post

  • Please keep comments related to topic. Whatever you do, don't spam!
  • Basic HTML tags are allowed:
    <a href> <abbr> <acronym> <blockquote> <code> <em> <strike> <strong>
  • Note: un-related or spam comments will be deleted. Also, we use the rel=nofollow tag, so there's even less of a reason to spam.

Trackback this postComments are directly below (arrow image)

Trackback this post

  1. February 10, 2009
  2. March 20, 2009
Back to top