changing html images on hover/a quick css trick
Changing an image on hover in css is a piece of cake. It's a common technique that has been used for a long time and received a number of improvements over the years (think css sprites). Changing an html image on hover is a little harder and when I ran into this very problem a week or so ago it had me stumped for about 30 seconds. More than enough to dedicate an article on a selection of solutions to refresh people's memory.
what we want to accomplish
Hovers on html images are not too common, as most images in html are purely content images and are not related to the actual design. One important exception is the site logo, which is best placed in html instead of css. It's common practice to put a home link on the site logo and when hovered, it's nice to see a hover state indication, subtle as it might be. To summarize what it is we want to do exactly:
- Place an image in the html source
- Change the look of the image when hovered
- Stay clear of any javascript and solve the problem using css only
- The image has to show up on print at all times, as seen on the page.
The final condition is the reason why we can't rely on css images only, and even though sprites can be used, we have to make sure only the base image shows up on print.
the first solution: sprites
a {display:block; width:100px; height:50px; overflow:hidden;}
a:hover img {margin-left:-100px;}
/* ie6 needs his fix*/
a:hover {zoom:1;}
Our first solution makes use of sprites. This means that both versions of the image are created in the same file. In this case, the image is 100px wide, so the hover state of the image is placed
100px to the right of the base image. We give the link the dimensions of the image and add overflow:hidden to hide the hover state. When
we hover, we simply pull the image to the left and up comes the hover state. IE6 is not very cooperative and needs a little fix, a simple
zoom:1 does the trick though.
A pretty easy trick, which shows up well on print too (as the overflow:hidden is applied), only when disabling the css altogether does this technique fail, as both states of the image will show up next to each other. Apart from that, the technique has good browser support with only IE6 being a little annoying (what else is new).
the second solution: separate images
a {display:block; width:100px; height:50px; background:url("logo-2.gif") left top no-repeat;}
a:hover img {position:absolute; left:-999em; top:-999em;}
/* ie6 needs his fix*/
a:hover {zoom:1;}
The second solution is a little dirtier, but shows up well even with css disabled. The idea is to make a separate image for the hover state and to place it behind the actual
image in css. When the link is hovered, we simply position the base image away and what remains is the hover state of the image defined in css. A simple trick, but effective,
with no lag as the css image is defined on the link and is loaded when the page is renderen for the first time. Again, IE6 needs a little push to make it work, adding a simple
zoom:1 is all it takes.
Apart from the little IE6 tweak this is a pretty handy solution, though it does require you to load two separate images. If you're aiming for speed, this might not be your choice of preference.
a third alternative: transparent images
a {display:block; width:100px; height:50px; background:#fff; overflow:hidden;}
a:hover {border:0px solid red; background:#00FF21;}
The third solution is the easiest to do in css but requires some graphical preparation and only works when doing color effects. Still, it's a nice technique that could use some more attention. The trick is to make part of your image transparent. You then define a base background color which you overwrite on hover. You can use gifs for simple images or pngs for more interesting masks. More information can be found in my article on png masks.
A very effective method, though hard to accomplish with png masks as ie6 has bad png support. Apart from that, also limited in effect as it can only be used to influence the color of your logo.
a final variation: css transparency
To finish off the article there's a final variation on the color theme described in the third alternative. Rather than use a transparent html image it's also possible to use css transparency to get a nice highlight effect. Here too you can do simple highlights using background colors or try more complex masks by using images. More information on this technique can be found on the SocialGeek blog.
rounding up
Maybe (read: probably) I missed some solutions, but these were the ones that sprung to mind immediately. They all have their pros and cons but between the three of them you should have more than enough options to accomplish what you want. Nothing too difficult or complex, but it gives your site that little extra.

Nice overview. I have gotten so used to the sprites technique that I use it nearly everywhere now. But as you point out that may not be the most stylish way of doing things.
I think the sprites technique is only workable if the image is defined in the css file. Considering html images, I'm much more in favor of the latter solutions provided in this article for the sole reason of the full sprite showing up when style sheets are disabled or unavailable (as pointed out in the article).
I always use the 2nd solution as it's the one that will work best in most situations.
Well, the second solution is my preferred one too, will be using it in my new blog design.
As for the first solution, I think there's an alternative way to handle it by clipping certain parts of the image in css (clip property). Ran into it the other day, have no idea how well it is supported cross-browser though.
i am used to the first one.Maybe the bad one,but i used to it.
I've got to ask: what is the picture that illustrates this article?
Hah!
It's actually a hovercraft (largest one in the world I believe). The craft of hovering etc ... :)
Ellooo,
Tried solution with the 2 images, but unfortunately if you do that in IE 7, and you try using applying it to 2 different buttons with 2 css id's, then IE 7 will use the first hover image on the second id... argh! The sprite image approach works better. In firefox there's a little wierdness though, it does something different if you do or , isn't that wierd???
Wout
I couldn't come up with a simple way of putting my lettering on the "non-hovered" image in the second solution. As it's presented, I would have to have my text as part of the actual image. I also would have to have an ID for each link and provide seperate background images and seperate base images for each link in each link's unique CSS (this also relates to Ellooo's comment). Too much muck.
I simply switched the "blank" background images via CSS a:hover, and then placed my text (once) in the link. If a user comes to the site with CSS disabled, the text link still shows. Anyone going to my site with CSS disabled is going to have a hard time making heads or tails of it anyway, and I suspect that's the case with most modern sites. I'll provide for the JS disabled, but having to provide for the CSS disabled may be a bit extreme and counterproductive. Like I said, the text links will still be there for the CSS disabled.
Here's the code with five links...
@djlebarron,
That works great, but its better if you have two images in one and move the background image, this ensures that there is no flicker or wait when the hover state is loaded.
Used the 2nd solution. I'm not a frontend person by trade (Ruby guy actually), but was able to use this elegant method very quickly and easily. I showed it to one of our designers and he really liked the implementation. I forwarded this post to him for a CSS talk he's giving later today. We're going to take a look at using the 2nd solution over sprites in certain areas of our site.
Thank you.
my cell of the table contains 3 (text) links to diffrent files.as i move over on the cell,my background color of that particular cell is being changed. but i want the color of all the 3 text also to change along with the background change. i am successful in changing the cell background. but not able to change all the 3 text colors at the same time. please help me out of this problem if u r willing. my email-id: ambilibmenon@yahoo.co.in
beautiful site you should be proud
* required fields