How to increase the performance of a website with CSS Sprites


You’re created a website, maybe using our “How to build a website from A to Z” guide, but you’ve noticed that loading times are rather long. There could be many reasons to explain this behavior, and there are some small tweaks you can implement to increase performance. Today we will talk about CSS Sprites.

What are sprites?

When you’re developing a website, it’s common to use background images that can create certain effects not possible using only XHTML+CSS. For instance, you can use them to create headers that have a peculiar font, or for menu buttons as well. Just to give you a more concrete example, let’s imagine a menu divided into four, and then create the following images:

single_image

Apply these images to the ‘hover’ state, using CSS:

single_image_hover

In total, 8 images, meaning 8 requests to the server, are requested; one per image.

A sprite is a series of images combined into one, divided into sections and edited through CSS. Looking at the example, you will see how the images are combined in the following way:

menu

The concept of a web sprite derives from the 1980s videogame era, when it was first developed to allow character’s movement across the screen. (Monkey Island’s famous Guybrush Threepwood is depicted in the image).

guybrush_sprite

Nowadays most of the popular websites use this type of imaging: this is an example found on Google websites:

google_sprites

How can I improve image menus using sprites?

Let’s see how you can create the menu shown in the example using the two methods, after which you will be able to notice a difference in the site’s overall performance. Start with a simple XHTML markup, a list of links:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
  <link rel="stylesheet" type="text/css" href="no_sprites.css" />
  <title>Menu without sprites</title>
</head>
</body>
<ul id="nav">
  <li class="home"><a href="#">Home</a></li>
  <li class="about"><a href="#">About</a></li>
  <li class="contacts"><a href="#">Contacts</a></li>
  <li class="portfolio"><a href="#">Portfolio</a></li>
</ul>
</body>
</html>

As you can see, each link has a class associated to it so that you can combine the CSS code. First let’s do some basic formatting, such as a reduction in margins and some editing to the text:

body,h1,ol,ul,li,p{margin:0;padding:0;}

body{
  background-color:#FFF;
  color:#000;
  font:75%/1.4 Helvetica,Verdana,Arial,sans-serif;
}

Now remove the default styles from the list and align the elements by applying a float on the left side:

...
#nav{
	list-style:none;
	margin:20px;
}

#nav li{
	float:left;
	margin:0 4px;
}
...

Look at the result, it looks like you’re on a good track: the elements are properly aligned horizontally and have a margin separating them. Before applying the images, it is important to change the dimension of the links so that they fit the image. In this case the dimensions are 100 pixels in width and 27 px in height:

#nav{
	list-style:none;
	margin:20px;
	text-indent:-9999px; //this rule hide the text
}

#nav li a:link, #nav li a:visited{
	display:block;
	width:100px;
	height:27px;
}
...

The display:block directive is very important, since it allows the entire area of the link to be clicked instead of just the text. You can also hide the link text, using the text-indent function. Let’s proceed by applying the images:

...
.home a:link, .home a:visited {background-image: url(home.png);}
.about a:link, .about a:visited {background-image: url(about.png);}
.contacts a:link, .contacts a:visited {background-image: url(contacts.png);}
.portfolio a:link, .portfolio a:visited {background-image: url(portfolio.png);}

.home a:hover, .home a:focus {background-image: url(homeh.png);}
.about a:hover, .about a:focus {background-image: url(abouth.png);}
.contacts a:hover, .contacts a:focus {background-image: url(contactsh.png);}
.portfolio a:hover, .portfolio a:focus {background-image: url(portfolioh.png);}
...

This part of the code might look intimidating, but in reality the rules are really simple: due images are associated to every class, one to define “normal” and “visited” states, and one for the “hover” and “focus” states (this last one is activated when a link is selected using the Tab key). The end result is functions perfectly, but you can still improve it through sprites. Note how the first time you hover the mouse over the link, there’s a slight delay in the transition between the two images: this delay is due to the loading time of the hover image. Let’s look at how to solve this.

How do I use sprites?

To understand how sprites work, think of looking at a poster through a small opening on a piece of cardboard. You’ll see that the angle of vision is limited, thus not allowing you to see the entire poster in one view and only providing you with a section of the image.

sprite_spiegate

As you can see in the image, using CSS we can move the background image. Since we have changed the link dimensions in the previous step, we are certain that only the relevant image portion will be visualized.

Another advantage of using sprites is that a minimum amount of change is made to the code, which interests only the CSS portion. The first edit is going to involve adding the same background image to all of the menu links:

...
#nav li a:link, #nav li a:visited{
	background-image: url(menu.png); //single image for all links
	display:block;
	height:27px;
	width:100px;
}
...

Once you have completed this, you will have to position the background by inserting the proper coordinates for each element. You can find these coordinates using any image-editing program, such as GIMP or Photoshop. In this case, it’s relatively simple, since all of the elements are of the same size. Let’s see how it comes out to be structured:

...
.about a:link, .about a:visited {background-position: -100px 0;}
...

Here we have used the background-position rule using horizontal and vertical movement as our parameters in the following order. As you have seen in the descriptive image, the “About” button used to occupy a space 100px from the left border and 0px from the top one. Since we will have to move the image to the left, the value to be inserted will have to be negative. The position of each element can be found by doing some simple arithmetic:

.home a:link, .home a:visited {background-position: 0 0;}
.about a:link, .about a:visited {background-position: -100px 0;}
.contacts a:link, .contacts a:visited {background-position: -200px 0;}
.portfolio a:link, .portfolio a:visited {background-position: -300px 0;}

.home a:hover, .home a:focus {background-position: 0 -28px;}
.about a:hover, .about a:focus {background-position: -100px -28px;}
.contacts a:hover, .contacts a:focus {background-position: -200px -28px;}
.portfolio a:hover, .portfolio a:focus {background-position: -300px -28px;}

And this is the final result.

Closing comments

The use of sprite images in the development phase of a website is not given much value. It can take several hours to create a sprite image, but one must also consider the advantages one gets in return. Most importantly, these are in the request load sent to the server, as well as the size of the downloaded files (as a matter of fact, the total image is smaller in size compared to all of the single images put together). Test results on the example we showed you in this article show that the version with multiple images has a loading time of 3.82 seconds. This is due to the continuous loading of the images in the “hover” state. While for the sprite version, a loading time of only 0.521 seconds was recorded.

single_images_small
image_sprites_small

A total savings of almost 50% is made (considering the loading times of a page).

However, a few remarks must be made: we feel that this technique is useful once a definite version of a site is created. This is because creating a sprite which contains all the elements of a site is quite intensive.

So we advise you to use single images during the development and testing phase, and sprites for the definite version of the layout. What do you think about it?

Master per Web Designer Freelance
In tutti questi anni abbiamo ricevuto centinaia di richieste di approfondimento sulle numerose tematiche del web design vissuto da freelance. Le abbiamo affrontate volta per volta. Ma ci siamo resi conto che era necessario fare qualcosa di più. Ecco perché è nato One Year Together, un vero e proprio master per web designer freelance che apre finalmente le porte al mondo del lavoro.
Scopri One Year Together »
[pdf]Scarica articolo in PDF[/pdf]
Tags: ,

The Author

Fond of web design, takes delight in creating (X)HTML+CSS layouts. A maniac of polished and tidy codes, the type of person you find in your house straightening the paintings hanging on the wall. He has made his mind of becoming a web designer with a capital “w”, and spends entire nights awake in order to make his dream come true.

Author's web site | Other articles written by

Related Posts

You may be interested in the following articles:

16 comments

  1. Garry Wallace

Trackback e pingback

  1. How to increase the performance of a website with CSS Sprites | Design Newz
    [...] How to increase the performance of a website with CSS Sprites [...]
  2. You are now listed on FAQPAL
    How to increase the performance of a website with CSS Sprites... You’re created a website, maybe using our How to build …

Leave a Reply

Current month ye@r day *