Skip navigation
Tyssen Design — Brisbane Freelance Web Developer
(07) 3300 3303

HTML image no preload rollovers

By John Faulds /

Recognise this? Chances are you do. Even if you don’t own a copy of Dreamweaver, it’s likely you would have come across the code it outputs for creating image rollovers in your travels looking at the code of other sites.


<script>
function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[ i])&&x.oSrc;i++) x.src=x.oSrc;
}
function MM_preloadImages() { //v3.0
  var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
    var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
    if (a[ i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[ i];}}
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[ i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[ i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[ i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}
</script>
<a href="#" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage('example','','/images/example_company_on.png',1)">
<img alt="Example company" height="167" name="example" src="/images/example_company_off.png" width="326" /></a>
				

Of course, there's been a much cleaner way of accomplishing the same thing using CSS and no javascript that's been a common practice for four or five years now. The limitation of the method described in that article is that you're only changing the background-image of the link and the link text must still actually be text in the HTML. That's fine in a lot of situations, but sometimes you want to use a custom font for your text and so need to modify the technique to incorporate image replacement.

But what about those instances for which using background-images isn't appropriate and the image should be in the HTML? Examples might include a company logo which you want to make a link back to the home page which is quite a common practice. There's a couple of different ways that this can be accomplished which allows the image to be in the HTML while still making the transition to the hover/focus state of the image seamless (i.e. with no delay while the image loads).

The first is similar to the example from wellstyled.com that I've linked to above in that it uses a single image with both on and off states in it. It might look something like this:

Example company logo including both on and off states

The way this method works is, instead of placing this image in the HTML, it's added as a background-image to the anchor and then moved into position on hover/focus using background-position and in its place in the HTML is a blank GIF or PNG which is given the same dimensions as a single state of the image (so roughly half the height but same width). There's a couple of problems with this method as I see it:

  1. Because the image in the HTML is blank, when the page is printed, you'll just get a blank space where the image should be (likewise if styles are turned off). Part of the reason for using an image rather than image replacement for something of this nature is so that the logo will appear in its graphic form when printed. The other factor is that a company logo is not always just a graphical representation of some text but is an item of content in its own right which brings me to the next problem...
  2. If you're using a blank placeholder image, you're not really inserting the image as content into your page. It seems to me that if you're going to put an image on your page, it should actually be the image you intend to be there and not a placeholder.

And because there is another way to accomplish this technique, there's no need to use a placeholder either. The HTML is very straightforward:


<h1>
  <a href="#">
    <img src="../images/example_company_off.png" width="326" height="167" alt="Example Company">
  </a>
</h1>
				

Remember to give the image an alt attribute that will describe it properly to someone who can’t see it, so if the logo is the only thing on the page that says what your company’s name is, then you want the company’s name as the alt text rather than something nondescript like ‘logo’ (or you might want it to say ‘return to Example Company’s home page’).

There are actually two slightly different ways to accomplish the rollover using CSS. For both, we’ll set the anchor to display: block and give it a width and height equal to the image, e,g.:


h1 a {
  display: block;
  width: 326px;
  height: 167px;
  background: url(../images/example_company_on.png) no-repeat
}
				

(I’m using a h1 because on the home page of a site that’s quite likely the tag I’d use for a logo or title that includes the company or site name.)

The first alternative for displaying the hover state of the image is to use a negative text-indent:


h1 a:hover { text-indent: -9999em }
				

The other is slightly more involved due to a quirk in IE<=6.


h1 a:hover img, .two a:focus img { display: none }
h1 a:hover { line-height: 1 }
				

With this method, we’re simply turning off the image in the HTML when it’s hovered so that the background-image behind it can be seen. The second rule is to overcome the IE quirk in that IE won’t change the state of elements nested within anchors on hover unless there is something set for the anchor itself. It also seems that some properties will trigger the change, while others won’t so in this case, line-height does and so does using a background-color (e.g. white in this case). But using a background-color of transparent won’t and neither does using text-decoration.

Finished examples of both

Because both the off state of the image (in the HTML) and the hover state (as the background-image of the anchor) are both loaded when the page does, there’s no lag when hovering over the image for the first time and because the image is in the HTML, it’ll appear on the page when it is printed. The best of both worlds!