Example: Using CSS Instead of Images for Menu Rollovers

This is a simplified example of a language selection menu found on the website of an international organisation:

We've taken this example and produced a similar low bandwidth version:

In the original version, two images are used for each of the languages. When the mouse pointer moves off or on to an image, the event is detected in JavaScript and the image is changed. Another image is used for the orange dividers.

Here's the JavaScript code:

langIndexes = new Array('en','fr','es');
langImagesOver = new Array();
langImagesOut = new Array();

for( i = 0; i < langIndexes.length; i++ ) {
  langImagesOver[langIndexes[i]] = new Image();
  langImagesOver[langIndexes[i]].src = langIndexes[i] + '_over.gif';
  langImagesOut[langIndexes[i]] = new Image();
  langImagesOut[langIndexes[i]].src = langIndexes[i] + '_off.gif';
 }

function swap(langCode,langStatus){
  if( langStatus ) {
    document.images[langCode].src = langImagesOver[langCode].src;
  }
  else {
    document.images[langCode].src = langImagesOut[langCode].src;
  }
}

Here's the HTML:

<div class="language">
<a href="#en" onmouseover="swap('en',1)" onmouseout="swap('en',0)">
<img src="en_off.gif" alt="English" title="English" name="en" width="67" height="20">
</a>
<img src="orange_divider.gif" width="1" height="20" alt="">
<a href="#fr" onmouseover="swap('fr',1)" onmouseout="swap('fr',0)">
<img src="fr_off.gif" alt="French" title="French" name="fr" width="73" height="20">
</a>
<img src="orange_divider.gif" width="1" height="20" alt="">
<a href="#es" onmouseover="swap('es',1)" onmouseout="swap('es',0)">
<img src="es_off.gif" alt="Spanish" title="Spanish" name="es" width="71" height="20">
</a>
</div>

and here's the CSS:

body { 
padding:0;
margin:0;
}

div.language { 
background-color: black;
float:left;
line-height: 65%;
}

img { 
border: 0;
}

The HTML can be simplified greatly by rewriting the links as a horizontal list:

<ul class="language">
<li><a href="#en" title="English">English</a>
<li><a href="#fr" title="French">Français</a>
<li class="end"><a href="#es" title="Spanish">Español</a>
</ul>

The rollover effect can be achieved by using the :hover pseudo class in CSS, which makes the JavaScript redundant. The orange separators can be rendered by setting the right hand border of each of the middle list elements. So we've eliminated all of the images.

body { 
padding:0;
margin:0;
font-family:Helvetica,Verdana,Arial,sans-serif;
font-weight:bold;
font-size:70%;
}

ul.language {
background-color:black;
float:left;
margin:0;
padding:6px 4px;
list-style-type:none;
}

.language li {
display:inline;
border-right: 1px solid #cc6600;
line-height: 70%;
margin:0;
padding:0px 12px;
}

.language li.end { 
border: none;
}

a {
color: white; 
text-decoration: none;
}

a:hover {
color: #bbd6ef;
}

The result will vary depending on font availability but another advantage of this technique is that the font can be made consistent with the fonts used on the rest of the page. The text will also scale with the user's chosen font size in their browser.

By using just HTML and CSS we've reduced the size to 630 bytes from the original 1338 bytes using HTML, Javascript and CSS, a saving of over 50%. More of the code is CSS, which can be cached and shared across pages. JavaScript is no longer required. And we saved 3-6 HTTP requests and 1050-2100 bytes for the images which are no longer needed.