Best way to do image rollovers?
Asked Answered
S

8

5

I want my main logo to change when mousing over.

I understand there are several ways to achieve this, and was wondering what's the best way for stability, browser compatibility, efficiency - and ease to setup.

Some ways I've found are:

  • Javascript (jQuery) replacement of the "src" attribute.
  • CSS using backgrounds and "hover"

Any more? What's best?

Selfservice answered 23/11, 2010 at 19:40 Comment(1)
I feel like this should be wiki-ed. It's a pretty common question and a good one to know how to answer for the intermediate frontend coder. Furthermore, it asks for the "best" solution to something that, has many solutions depending on the circumstances.Dithyramb
D
10

Bottom line

For content-ful images, you want to have the src in the HTML markup. You want to use the Javascript solution and put the rollover image in an attribute.

For content-less images UI elements, especially ones that are common across the site or duplicated, a straight CSS solution would be the best (so you don't have to re-declare the image locations at each invocation). Among the CSS solutions, sprites are the best since they don't require preloading overhead.

The Javascript solution

HTML:

<img src="/img/one.jpg" data-rollover="/img/two.jpg" />

In jQuery:

$(function(){
  $('img.rollover').hover(function(){
    var e = $(this);
    e.data('originalSrc', e.attr('src'));
    e.attr('src', e.attr('data-rollover'));
  }, function(){
    var e = $(this);
    e.attr('src', e.data('originalSrc'));
  }); /* a preloader could easily go here too */
});

Sample implementation: http://jsfiddle.net/dtPRM/1/

Benefits: It's easy; it makes sense; it works with minimal additional markup once you have your library set up.

Downsides: Requires Javascript and overhead of loading the jQuery library.

Probably the best option. If your user is using a browser where rollovers are relevant (probably the case), they have the Javascript capabilities to run this option. The folks who have intentionally turned Javascript off for some reason will clue in if you leave a little <noscript> note saying that they may not get the full featureset.

The CSS solution: Best

HTML:

<div id="img1" />

CSS:

div#img1 {
  height: 400px;
  width: 300px;
  background: url('http://dummyimage.com/600x400/000/fff') no-repeat top left;}
div#img1:hover {
  background-position: top right;}

Sample implementation: http://jsfiddle.net/dtPRM/5/

Personally, I think that for content-ful images, this is an even worse option than the CSS + two background images solution. You're separating the HTML markup from the semantic value of the display.

If you're using content-less images like UI elements, though, this is the best solution in my opinion.

The CSS solution: Also okay

Another CSS option is available that doesn't involve background images (preferred among the CSS solutions if you want to have the image tags in the HTML, like for semantically meaningful images).

<div class="rollover">
  <img class="rollover" src="http://dummyimage.com/600x400/000/fff" />
  <img class="" src="http://dummyimage.com/600x400/fff/000" />
</div>

CSS (I use the :not pseudo-selector here, but it's pretty easy to avoid using it; I also think I got the classnames semantically backwards):

div.rollover img:not(.rollover) {display: none;}
div.rollover:hover img:not(.rollover) {display: inline;}
div.rollover:hover img.rollover {display: none;}

Sample implementation: http://jsfiddle.net/dtPRM/2/

Benefits: Semantically sensible compared to the previous CSS solution of putting all the information the stylesheet.

Downsides: Extraneous markup needed.

Comment: This one may automatically pre-load depending on whether the browser calls for it.

Bottom line: A decent fallback if option (1) is unavailable because you absolutely need IE2 compatibility or non-JS support.

The CSS unsolution: Stay away

I mention this only because you mentioned it in the question. I wouldn't use it.

HTML:

<div id="img1" />

CSS:

div#img1 {
  height: 400px;
  width: 600px;
  background: url('http://dummyimage.com/600x400/000/fff') no-repeat top left;}
div#img1:hover {
  background-image: url('http://dummyimage.com/600x400/fff/000');}

Sample implementation: http://jsfiddle.net/dtPRM/4/

Benefits: Widely compatible; all you really need to support is background images and hover.

Downsides: Semantically weird to put images in CSS and to centralize it there. Makes future modifications more difficult. That being said, if you have a scenario that warrants a rollover image, there's a good chance it may be a non-content image (e.g., a UI element), in which case CSS would be semantically (perhaps) even more suitable than a regular image. See the note on sprites below.

Other downsides: You'd have to be careful to declare image height and width (a good practice anyway, but it may get cumbersome when you just want to get things done). Users viewing on mobile browsers that may treat CSS background images unusually.

Even more downsides: If you want to layer a preloader on top of it, you're going to be using Javascript and somehow selecting the rollover-able elements, and at that rate, you may as well use Javascript for everything.

Bottom line: Don't use this for content-ful images. If you must stay away from Javascript, use sprites for UI elements and the alternate solution for semantically meaningful images.

Dithyramb answered 23/11, 2010 at 20:19 Comment(2)
As of jQuery 1.4.3, you can access HTML5 data- attributes with .data(). api.jquery.com/dataGuiscard
Thanks for this nice overview. I used the "The CSS solution: Also okay" because of it's simplicity of editing (both URLs in one place) and to be compatible with retina.js (that switches in highres-images for all img-tags). But it turns out, that this solution is buggy on touch-devices: If the hover-img is linked, the link isn't allways followed, when tapped. So I deactivated the hovering for touch-devices, as it doesn't make sense there anyway. (Used this detection)Narcotic
S
4
#btn{
width:100px; height:100px;/*the dimensions of your image*/
background:url(bird.png) left top no-repeat;
}
#btn:hover{
background-position:left bottom;/* pixel references can be used if prefered */
}

Using an image like this:

alt text

Note: Avoid JS image replacements as you will incur a short image load time if images are not cached before.

Hope this helps bro!

W.

Sholokhov answered 23/11, 2010 at 19:49 Comment(3)
The images from css are not precached either, specially in IEJempty
When you're using a sprite, the browser loads the whole sprite image (assuming the element that requires it is visible). Here, it is, so the mouseover portion is loaded, ostensibly resulting in preloading.Dithyramb
What kind of element should #btn be for best practice? A div with nothing in it?Poussin
T
3

CSS using backgrounds and "hover"

Use CSS sprites, in other words combine both images into one and then use css :hover to shift the image.

One advantage of using CSS is that it'll work even if JavaScript is turned off.

One advantage of using a single image is it'll avoid the extra HTTP request.

See: http://css-tricks.com/css-sprites/

Tools to help generate image and CSS:

Theravada answered 23/11, 2010 at 19:45 Comment(0)
F
0

You should use a :hover CSS rule.

Fachini answered 23/11, 2010 at 19:41 Comment(0)
C
0

CSS by far. Though you may want to precache your image with javascript.

Crowns answered 23/11, 2010 at 19:42 Comment(0)
C
0

Image rollovers using 'sprites' List a part - sprites CSS

Comestible answered 23/11, 2010 at 19:42 Comment(0)
T
0
$('#div1').hover(function(){
  this.style.color='white';
},function(){
 this.style.color='black;
});

or

$('#div1').onmouseover()...
$('#div1').onmouseout()...
Totalizator answered 23/11, 2010 at 19:45 Comment(0)
S
0

Use CSS sprites and the :hover psuedo-class in CSS. Here's why:

  1. Switching image source either through JS or through the CSS will cause a "blink" on the first mouse-over while the new image is downloaded by the browser. If you use the sprite, it's just one image that changes position, so no blink.

  2. A single image reduces HTTP requests, making the site load faster in general.

  3. It works if the user has JavaScript disabled.

  4. It's supported by all browser types (desktop, anyways, phone browsers without a :hover state don't count for this anyways).

More information: http://css-tricks.com/css-sprites/

Shaddock answered 23/11, 2010 at 19:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.