CSS Sprites

The widely used phrase CSS sprites refers to the practice of combining graphics used as backgrounds into a single file, then using CSS Background-Position properties to offset them.

The reasons for doing this include:

  • Decreased Total File Size: Combining a number of images into one will make a smaller file size.
  • Reduced Server Requests: Every image in your site represents an http request. The more requests, the slower the page load.
  • Ease of Maintenance: It’s far easier to modify a single file than a bunch of them.

Consider this screenshot of part of the front page of the Yahoo! Canada site:

Yahoo Screenshot

The menu on the left is a simple Unordered List. Each of the 19 LIs in the list contains a link. Each link is set to display: block and has the same background image. All but the first use of the background image is offset to match its corresponding link text.

Let’s build it.

First, download the menu image files.

Then make an HTML file with a UL with the text from the screenshot. Make each line of text a “testing” link ( href = “#” ).

<ul id="menu">
  <li><a href="#">Mail</a></li>
  <li><a href="#">Answers</a></li>
  <li><a href="#">Autos</a></li>
  <li><a href="#">Connected TV</a></li>
  <li><a href="#">Dating</a></li>
  <li><a href="#">Directory</a></li>
  <li><a href="#">Finance</a></li>
  <li><a href="#">Flickr</a></li>
  <li><a href="#">Food</a></li>
  <li><a href="#">Games</a></li>
  <li><a href="#">Horoscope</a></li>
  <li><a href="#">Jobs</a></li>
  <li><a href="#">Messenger</a></li>
  <li><a href="#">Movies</a></li>
  <li><a href="#">People Finder</a></li>
  <li><a href="#">Search</a></li>
  <li><a href="#">Shine</a></li>
  <li><a href="#">Sports</a></li>
  <li><a href="#">Updates</a></li>
  <li><a href="#">Weather</a></li>
  <li><a href="#">Yellow Pages</a></li>

Give the UL an ID of “menu” — remember, we can give an ID to any element, not just DIVs.

Style the menu as below. Give it a width, remove the bullets, and zero the padding-left and margin-left (space reserved for the bullets). Give it a border as well.

#menu {
	list-style-type: none;
	width: 160px;
	margin-left: 0;
	padding-left: 0;
	border: 1px solid #999;

Give the List Items a border also.

#menu li {
	border: 1px solid #CCC;

Set the link font type, size, and decoration (the latter to remove the underlining). Note: we could also have set these properties on a parent element of the UL.

Put in padding-left of 30px. This will leave room for our background image. Obviously, in this example we also need to set the image not to repeat. Finally, setting display: block will make the link take up the entire width of its containing element.

#menu li a {
	text-decoration: none;
	color: #333;
	font-family: Verdana, Geneva, sans-serif;
	font-size: 13px;
	line-height: 30px;
	padding-left: 30px;
	display: block;
	background-repeat: no-repeat;
	background-image: url(yahooIcons.gif);
	background-position: left top;

While we’re here, if we want we can also choose a rollover image sprite for our menu. At the end of this exercise, however, I will ask you to come up with an even better way of doing this.

#menu li a:hover {
	background-image: url(yahooIconsHover.gif);

Now, all we need to do is offset the background image by the approximate size of each icon. To do this, add a class to each anchor tag. For the class name, just use the link text, or something similar. Here’s a few of the LIs with these new classes attached:

<ul id="menu">
  <li><a href="#" class= "mail" >Mail</a></li>
  <li><a href="#" class = "answers" >Answers</a></li>
  <li><a href="#" class = "autos" >Autos</a></li>

And here are the values I used to position the background image so that each icon would show in the appropriate place. To get these values was a process of trial and error: I just eyeballed everything and adjusted by a pixel or two here and there.

#menu .mail {
background-position: 0px 0px;

#menu .answers {
background-position: 0px -24px;

#menu .autos {
background-position: 0px -50px;

#menu .connected {
background-position: 0px -77px;

#menu .dating {
background-position: 0px -102px;

#menu .directory {
background-position: 0px -130px;

#menu .finance{
background-position: 0px -157px;

#menu .flickr {
background-position: 0px -184px;

#menu .food {
background-position: 0px -212px;

#menu .games {
background-position: 0px -238px;

I could go on and style the rest of the List Items, but I’m sure you get the gist of the technique by now.

However, we used an extra image for the hover pseudo-class. Can you think of an easy way to have the image rollover effect without adding another download? If so, please do it and show it to me.

Additional Reading on CSS Sprites:

From alistapart.com: CSS Sprites: Image Slicing’s Kiss of Death