Web Developer

Image Rollovers

For whatever reason, users like eye candy.  They like when things are dynamic and change based on their input.  They like when they move their mouse over an image and the image changes.  This basic effect, called an image rollover, is easily accomplished using JavaScript.  The general process involves creating 2 image objects in memory.  Then swap the images on the screen based on where the user's mouse is on the screen.

Another useful mechanism for image rollovers is to sidestep Netscape's inability to handle the a:hover CSS pseudo class.  Since Netscape doesn't let us change the color of text on the fly, it is a relatively small leap to make to use text-based images of differing colors and swap them out when necessary - something that is relatively simple for both browsers.

Before you begin, you will need at least two images - one that represents an "off" state and one that represents an "on" state.  You'll also need an <img> element with a name attribute as a container for the rollover.  Finally, it is customary to specify the "off" state image as the src attribute for the <img> element.  In effect, you are assuming that the user's mouse will not be on the image when the page first loads.

Next, you'll capture the onMouseOver and onMouseOut events to do the actual swapping.  It would make sense to capture the events inside the <img> element and in Internet Explorer this mechanism would work beautifully.  As you've probably guessed, in Netscape this approach fails as the <img> element doesn't support the two events we need to capture.  So we'll trick Netscape by wrapping the rollover effects inside an <a> element which does support our two events.  The good news is that moving the events to the <a> element still works fine in IE.  So let's get started!

Here is the simple document we'll start with:

<html>
<head>
<title>rollover</title>
</head>
<body>
<p>
<img name="img1" border="0" src="http://www.bright-moments.com/webdeveloper/images/off.gif" width="100" height="20">
</p>
</body>
</html>

Now let's add the script to the <head>.  In the script, we'll create two image objects and then assign an image file to the src property of each object.  By creating the image objects in our script, we avoid any delays in downloading the new image when we swap them out.  The effect is an instantaneous rollover as the images already exist in memory.  Here's our page with the script for creating the image objects:

<html>
<head>
<title>rollover</title>
<script language="JavaScript">
var imgOn = new Image();
imgOn.src = "http://www.bright-moments.com/webdeveloper/images/on.gif";
var imgOff = new Image();
imgOff.src = "http://www.bright-moments.com/webdeveloper/images/off.gif"
</script>
</head>
<body>
<p>
<img name="img1" border="0" src="http://www.bright-moments.com/webdeveloper/images/off.gif" width="100" height="20">
</p>
</body>
</html>

Notice that both objects get separate src properties.  In any real world application, you would use relative paths and therefore avoid the long URLs given.  After this project, we'll assume that you are using relative URLs and give you access to the files as a download.

The next step is to write the functions that will actually handle the image swap for us  Add these two functions to your script:

function on(img){
document[img].src = imgOn.src;
}
function off(img){
document[img].src = imgOff.src;
}

Both of these functions take a parameter that denotes the name of the <img> element you want to apply the effect to.  In our case, we'll be passing in 'img1' to the function as that's the name attribute of our element.  But what does "document[img]" mean?  Well, as you've seen before, the square brackets ([]) indicate that an array is in use.  The cool part is that JavaScript keeps an array of all the elements on any document in the document[] array.  You can then reference any element in the array by either its index (the order in which it appears in the document) or, more importantly for us, by its name.  So, in our case "document[img]" means find the element on the page that contains a name attribute equal to whatever is passed in to the function.  We'll call on('img1') or off('img1') because that's what we named our <img> element.

The next lines actually do the image swapping for us.  First, the interpreter will search for an element on the document called img1 - that's the document[img] part.  Next it will assign the src of either the imageOn or imageOff object to the <img> element's src attribute.  In essence, you are changing the src attribute of the <img> element on the fly!

The final step is to attach our functions to the onMouseOver and onMouseOut events.  As noted before, we'll wrap up the <img> element inside an <a> element so that it will work in both browsers.  Here is the the finished code:

<html>
<head>
<title>rollover</title>
<script language="JavaScript">
var imgOn = new Image();
imgOn.src = "http://www.bright-moments.com/webdeveloper/images/on.gif";
var imgOff = new Image();
imgOff.src = "http://www.bright-moments.com/webdeveloper/images/off.gif"
function on(img){
document[img].src = imgOn.src;
}
function off(img){
document[img].src = imgOff.src;
}
</script>
</head>
<body>
<p><a href="#" onMouseOver="on('img1')" onMouseOut="off('img1')">
<img name="img1" border="0" src="http://www.bright-moments.com/webdeveloper/images/off.gif" width="100" height="20">
</a></p>
</body>
</html>

See It In Action

Notice that we are truly tricking the browser in the <a> element by specifying "#" as the href attribute.  In this case "#" means null - no hyper jump will take place.  Second, notice that we are passing Strings to the functions.  This is important as the document[] array uses Strings to keep track of all the named elements (it uses integers to keep track of all the elements by index).

A Better Example

The above example demonstrates the rollover effect but not much else.  In fact, it's actually a bad use of iconography isn't it?  We've created a button that doesn't behave like a button.  Since we've wrapped the button inside an <a> element, the cursor even changes to a hand indicating that some jump will take place.  Of course, we affixed the "#" sign to the href attribute so we know nothing will happen - but the user will not know this.  Bad!

So let's create some image rollovers that are a little more useful.  The process will be the same - we'll create our image objects in memory, write the functions that perform the rollovers, and attach the functions to event's inside an <a> element.  Along the way, we'll see that we can get the buttons to actually behave like buttons.  Here are links to the images.  Click on the link to each image, then right click on the image and choose Save Image As...  Save the images to a folder on your hard drive.  You'll then create the HTML document in the same folder.  This allows us to use relative paths.

img1on.gif
img1off.gif
img2on.gif
img2off.gif

We'll have to modify our image swapping functions as they will have to deal with more than one <img> element on the page.  In this case we'll use two elements but this script is much more robust and can handle any number of images.  One final thing to note:  all of the image files and names have a similar pattern.  You do not have to use this pattern but it works well as you can then refer to each particular object in the same fashion.  Just make sure that whatever pattern you choose to use is one with which you'll stick.  Here's the code:

<html>
<head>
<title>rollover2</title>
<script language="JavaScript">
var img1off = new Image();
img1off.src = "img1off.gif"
var img1on = new Image();
img1on.src = "img1on.gif"
var img2off = new Image();
img2off.src = "img2off.gif"
var img2on = new Image();
img2on.src = "img2on.gif"
function on(img){
document[img].src = eval(img+'on').src;
}
function off(img){
document[img].src = eval(img+'off').src;
}
</script>
</head>
<body>
<p><a href="http://www.yahoo.com" onMouseOver="on('img1')" onMouseOut="off('img1')">
<img name="img1" border="0" src="img1off.gif" width="200" height="50"></a></p>
<p><a href="http://www.google.com" onMouseOver="on('img2')" onMouseOut="off('img2')">
<img name="img2" border="0" src="img2off.gif" width="200" height="50"></a></p>
</body>
</html>

The only new thing about this script that you haven't seen yet is the use of the eval() method.  The eval() method takes a string argument and turns it into JavaScript.  Since we need to append either 'on' or 'off' to any image, we need to pass the string we received as a parameter to the function concatenated with either 'on' or 'off' to figure out which object we are actually talking about.

See It In Action

This second example is by far the more powerful as it is generic.  The second example allows you to create as many rollover images as you'd like on the page and demonstrates how to get around some of Netscape's limitations.  It also demonstrates how to get around both browsers' font limitations: simply create images using any fonts you'd like.  Of course this does nothing for your download times!