Sprites are two-dimensional graphics created by combining smaller images into a larger one, positioned at specific X and Y coordinates.
To display one image from this combined image, you can use the CSS background-position
property to define the exact location of the image to be shown.
Web pages with many images, especially small ones like icons and buttons, can load slowly and require multiple server requests.
Using image sprites instead of separate images reduces the number of HTTP requests a browser makes, greatly improving the loading time and overall performance of the website.
Note: Fewer HTTP requests lead to faster response times, making the web page more responsive for users.
Check out the examples below. In the non-sprite version, when you hover over the browser icons for the first time, the hover image appears after a delay because it's loaded from the server on hover. The normal and hover images are separate.
In the sprite version, since all images are combined, the hover image appears immediately, creating a smooth hover effect.
![]() |
![]() |
By using the CSS sprite technique shown in [EXAMPLE - B], we reduced the number of HTTP requests by 9 and the total image file size by 38.2 KB compared to [EXAMPLE - A]. This is a significant improvement even in a small example. Imagine the impact on a full website.
The complete process of creating this example is described below.
We created this sprite by combining 10 separate images into one image (mySprite.png). You can create your own sprite using any image editing software you prefer.
Tip: For simplicity, we used icons of the same size and placed them close together for easy offset calculation.
Finally, with CSS, we can display only the part of the sprite we need.
First, we create a class .sprite
that loads our sprite image. This prevents repetition, as all items share the same background image.
.sprite {
background: url("images/mySprite.png") no-repeat;
}
Now, we need to define a class for each item we want to display. For instance, to show the Internet Explorer icon from the sprite, the CSS would be:
.ie {
width: 50px; /* Icon width */
height: 50px; /* Icon height */
display: inline-block; /* Display icon as inline block */
background-position: 0 -200px; /* Icon background position in sprite */
}
Now you might wonder how we got those pixel values for background-position
. Let's explain. The first value represents the horizontal position and the second represents the vertical position of the background. The upper-left corner of the Internet Explorer icon touches the left edge, so its horizontal distance from the starting point (top-left corner of the sprite) is 0. Since it's in the 5th position, its vertical distance from the sprite's starting point is 4 x 50px = 200px
, as each icon's height is 50px.
To display the Internet Explorer icon, we need to move its upper-left corner to the starting point (top-left corner of the sprite). Since this icon is 200px down, we shift the whole background image (mySprite.png) up by 200px. This is done by using a negative value, -200px, because a negative value moves it up while a positive value would move it down. There's no horizontal offset needed as there are no pixels before the upper-left corner of the icon.
Tip: Experiment with the background-position
property values in the examples below to understand how the offsets work.
In the previous section, we learned how to display a single icon from an image sprite. Now, we will take it a step further by creating a navigation menu with a rollover effect, as shown in [EXAMPLE - B].
We'll use the same sprite image (mySprite.png) to build our navigation menu.
We will start by creating our navigation menu using an HTML unordered list.
<ul class="menu">
<li class="firefox"><a href="#">Firefox</a></li>
<li class="chrome"><a href="#">Chrome</a></li>
<li class="ie"><a href="#">Explorer</a></li>
<li class="opera"><a href="#">Opera</a></li>
<li class="safari"><a href="#">Safari</a></li>
</ul>
This sections will describe how to transform the simple unordered list above into a sprite image-based navigation menu using CSS.
By default, HTML unordered lists come with bullets. We'll remove the default bullets by setting the list-style-type
property to none
.
ul.menu {
list-style-type: none;
}
ul.menu li {
padding: 5px;
font-size: 16px;
font-family: "Trebuchet MS", Arial, sans-serif;
}
Next, we'll set common CSS properties for all links, such as color
, background-image
, display
, and padding
.
ul.menu li a {
height: 50px;
line-height: 50px;
display: inline-block;
padding-left: 60px; /* To shift text off the background image */
color: #3E789F;
background: url("images/mySprite.png") no-repeat; /* All links share the same background image */
}
Now, we'll define a class for each menu item, as each item in the image sprite has a different background-position
. For example, the Firefox icon is at the top-left corner of the sprite, so its background position is 0. Similarly, we'll define the background position for other icons.
ul.menu li.firefox a {
background-position: 0 0;
}
ul.menu li.chrome a {
background-position: 0 -100px;
}
ul.menu li.ie a {
background-position: 0 -200px;
}
ul.menu li.safari a {
background-position: 0 -300px;
}
ul.menu li.opera a {
background-position: 0 -400px;
}
Adding hover states follows the same principle as adding the normal states. Move the upper-left corner of each hover image to the top-left corner of the sprite. You can calculate the background-position
using this formula:
Vertical position of hover state = Vertical position of normal state - 50px
Since hover images are just below the default state and each icon is 50px tall. The hover state doesn't need a horizontal offset because the upper-left corner remains unchanged.
ul.menu li.firefox a:hover {
background-position: 0 -50px;
}
ul.menu li.chrome a:hover {
background-position: 0 -150px;
}
ul.menu li.ie a:hover {
background-position: 0 -250px;
}
ul.menu li.safari a:hover {
background-position: 0 -350px;
}
ul.menu li.opera a:hover {
background-position: 0 -450px;
}
Done! Here is our final HTML and CSS code after combining the whole process:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Example of Sprite Navigation Menu</title>
<style>
ul.menu {
list-style-type: none;
}
ul.menu li {
padding: 5px;
font-size: 16px;
font-family: "Trebuchet MS", Arial, sans-serif;
}
ul.menu li a {
height: 50px;
line-height: 50px;
display: inline-block;
padding-left: 60px; /* To sift text off the background-image */
color: #3E789F;
background: url("images/mySprite.png") no-repeat; /* As all link share the same background-image */
}
ul.menu li.firefox a {
background-position: 0 0;
}
ul.menu li.chrome a {
background-position: 0 -100px;
}
ul.menu li.ie a {
background-position: 0 -200px;
}
ul.menu li.safari a {
background-position: 0 -300px;
}
ul.menu li.opera a {
background-position: 0 -400px;
}
ul.menu li.firefox a:hover {
background-position: 0 -50px;
}
ul.menu li.chrome a:hover {
background-position: 0 -150px;
}
ul.menu li.ie a:hover {
background-position: 0 -250px;
}
ul.menu li.safari a:hover {
background-position: 0 -350px;
}
ul.menu li.opera a:hover {
background-position: 0 -450px;
}
</style>
</head>
<body>
<ul class="menu">
<li class="firefox"><a href="#">Firefox</a></li>
<li class="chrome"><a href="#">Chrome</a></li>
<li class="ie"><a href="#">Explorer</a></li>
<li class="opera"><a href="#">Opera</a></li>
<li class="safari"><a href="#">Safari</a></li>
</ul>
</body>
</html>