www.benchampion.com

Image mouseovers in CSS without preloading

by Ben Champion, 2008. Copyright © 2024

Converted from a Space Socket Tutorial Post, using the BBCode to HTML converter by Dagon Design, Quick Escape, and my bare hands (i.e. various editors).

This tutorial assumes a basic knowledge of CSS, but the code is fairly well-commented, so you might be able to figure it out even if you're just learning.

Introduction
I learned this technique from a website I can't seem to find now...If someone finds a site with this same trick listed, please post the link, so that I can see if it's the one I learned this trick from (and give due credit).

Now, let me describe this trick. You want to do a mouseover (using CSS), so that one image is displayed when the mouse is not over a button, then display another when the user rolls their mouse over the button. The problem is that most browsers seem not to download the rollover image until they need it, in other words, until the user puts their mouse over the button. This will mean that there will usually be a lag when the user puts their mouse over a button for the first time while the image is downloaded. This is a bit ugly. See http://basc.spacesocket.com/tut1/problem.html

What can you do to stop this? One way is preloading the images somehow, so that the browser downloads the rollover image when the page is loaded. Then there won't be a lag. I won't go into this technique here, because I've never really used it. That's because I use the trick that I introduce here.

Basically, the trick is that we combine our two images into a single image. We then set the display size of the image to be the size of one of the images (they will both be the same size of course). To get the rollover effect, we use the :hover pseudoclass in CSS to change where the background starts. Don't worry if you don't understand this short explanation, I will go into more detail later.

Images
To make a rollover button with images, we first need to start with some images! I quickly made a button and a rollover image in the GIMP (http://www.gimp.org/ or if you're on Windows http://gimp-win.sourceforge.net/). You can really make your image in any image editor, it's not critical.

Here are my images:

button.jpg:
button.jpg

button_over.jpg:
button_over.jpg

Note that the size of each image is 70 (width) by 23 (height). This will be useful later.

These are the pictures that we will use for our rollover. The first (button.jpg) is the "normal" image, the second (button_over.jpg) is the "rollover" image.

A Rollover without the Trick
We can get a rollover effect with making a "button" class for the <a> tag (you can do this for any HTML tag, I just used <a> as an example, since most buttons are going to be links). Here's the CSS code (or here):

/* The normal button, when user is not doing a mouseover */
a.button
{
  /* This option insures that the full image will be displayed */
  display: block;
  /* These are self explanatory :-) */
  width: 70;
  height: 23;
  /*
  Set the following attributes for the background:
  background colour: white
  background image: button.jpg (Our "normal" image)
  background repeat type: Don't repeat
  background attachment: Scroll with element (Not really relevant)
  background positioning (relative to the left edge of the element, in this case
  a link): 0px 0px (this setting will be important to "the trick" later on)
  */
  background: white url(button.jpg) repeat scroll 0px 0px;
}
a.button:hover /* Set the attributes when user hovers over link */
{
  display: block;
  width:70;
  height:23;
  /*
  Same settings as above, but we want to change the background image to our
  "rollover" image, button_over.jpg
  */
  background: white url(button_over.jpg) repeat scroll 0px 0px;
}

The corresponding HTML code is (also here):

<html>
<head>
<head>
  <title> Rollover with Problems </title>
  <!-- Link in the stylesheet -->
  <link rel = "stylesheet" type = "text/css" href = "rollWithoutTrick.css" />
</head>

<body>
<p>
<!-- Our button -->
<a class = "button" href = "problem.html">A Link</a>
</p>
</body>
</html>

The Problem with the above Code
As the name of the page, problem.html, might imply, there are a few problems with this code. Firstly, there are various formatting problems; these can be solve easily with a few additional attributes in the CSS file (which I will do below). The more important issue is that there's a lag when you first put your mouse over the button, while your browser downloads the "rollover" image. Obviously, if you have a really fast internet connection, this lag will be quite slight, but the lag is still ugly. Also, what if there's a temporary period where the server is really busy? This lag will certainly be accentuated (assuming that "Joe Websurfer" hasn't visited your site before, and so his browser hasn't stored the rollover image).

All in all, it's a bad idea to have two separate images without insuring that the second ("rollover") image will be already loaded into the users browser. As I mentioned, there are ways of preloading images into browsers, but I think this is a bit difficult. You can Google "preloading images" if you like.

The Solution/The Trick
You'll be pleased to know that there's a easy-to-understand solution. Notice that the "normal", non-"rollover" image IS loaded when the user first visits the site. If we combine the two images into one, then both images will be loaded! The combined image looks like:

button_and_over.jpg:
button_and_over.jpg

The CSS code we will write will "select" the part of the image we want to use for each appearance of the button:

We want this selected for the "normal" mode of the button:
button_select.jpg

And this selected for the "rollover" mode:
button_over_select.jpg

How do we do this? Well, we can select the size of our "selection window" using the side and width attributes in the CSS file. How to we change the position of the "selection window"? Well, we'll do this using the "position" (currently 0px 0px) part of the background attribute. Actually, the "selection window" will be in one place, and we're just moving the background image underneath, but it has the same effect.

Also, we can change the colour, underlining, and alignment of the text, because they're a little ugly as they are.

The new CSS code is (also here):

/* The normal button, when user is not doing a mouseover */
a.button
{
  /* This option insures that the full image will be displayed */
  display: block;
  /* These are self explanatory :-) */
  width: 70;
  height: 23;
  /* NEW Set the font color to black */
  color: black;
  /* NEW No underlining, or other text decoration */
  text-decoration: none;
  /* NEW Align text in the centre */
  text-align: center;
  /*
  Set the following attributes for the background:
  background color: white
  EDITED background image: button_and_over.jpg (Our combined image)
  background repeat type: Don't repeat
  background attachment: Scroll with element (Not really relevant)
  background positioning (relative to the left edge of the element, in this case
  a link): 0px 0px
  */
  background: white url(button_and_over.jpg) repeat scroll 0px 0px;
}
a.button:hover /* Set the attributes when user hovers over link */
{
  display: block;
  width:70;
  height:23;
  color: black;
  text-decoration: none;
  text-align: center;
  /*
  Same settings as above, except:
  EDITED background postioning (relative to the left edge of the element, in this case
  a link): -70px 0px
  NEW This will move the background image 70 pixels to the left, so that our second
  button, the "rollover" one, is displayed.
  */
  background: white url(button_and_over.jpg) repeat scroll -70px 0px;
}

And the new HTML (it's here also):

<html>
<head>
<head>
  <title> Improved Rollover </title>
  <!-- Link in the stylesheet -->
  <link rel = "stylesheet" type = "text/css" href = "rollTrick.css" />
</head>

<body>
<p>
<!-- Our button -->
<a class = "button" href = "fixed.html">A Link</a>
</p>
</body>
</html>

Voila! We have a button that changes when you put your mouse over it, and there's no lag when we switch from normal to "rollover" mode

Useful Links
The following is a list of some useful links relevant to the article (some of these are already in the article, I'm just repeating them).

Final Comments
Feel free to experiment with the code above, and edit it to suit your purposes.

I also just learned of another way of doing this rollover trick from sardonic. The the two images can be "glued" together vertically, rather than horizontally. You get the same effect, it's just a different way of doing things.

If anything I said above was unclear, or if I made a mistake (grammar and spelling INCLUDED), please (PLEASE!) contact me and let me know. I'd really like to make sure that this is a good and useful tutorial.

Copyright © 2024 Ben Champion