Posted on: January 5, 2018Updated: February 25, 2018
What are CSS sprites and why use them?
Update: Please note that the layout has recently been changed and that the side navigation on desktop no longer uses images but what is said in the following article still remains true.
Basically, in one sentence, CSS sprites are images that contain more than one image together as a single file. While this may seem counter productive at first, to put images together in your favourite image manipulation toolkit, it is actually easier to do and more beneficial for your website performance wise. In this article I mentioned that all the images should be compressed to boost site's performance. Well, to extend my thought on that, it's always better to have a single image loaded on a HTTP request than multiple images. This, however, begs a question whether that image might exceed the file size of all those smaller images together, especially if these images are not loaded through request at the same time, and thus slow down the loading time?
Looking at it from this perspective, no doubt but, on the other hand, we have forgotten about the number of handshakes a client and the server need to make to achieve the same result. It is shown that the latter outperforms the former unless your manual spirte generation has gone completely out of hands.
There is another reason why generate sprites. Sooner or later everyone comes to a point where a background image will be used as a hover effect on top of a background image. So those in the know will now probably remember the blinking effect. This is because the server has to load a hover image after the page was already loaded. Once the image was loaded in cache, it's fine, but coming for the first time, it has that bug like blinking effect. With sprites on the other hand, both images are loaded as one and then only the background position changes on CSS hover which solves the issue but enough talking for now, let's take a look at live example on this website.
So if you look at the navigation on the desktop design, hypothetically it would have a background image:
On hover effect, it would have to load another image:
You can easily try out this one yourself if you want to. Just save both images and place them on a remote server in the root folder and then call them from a HTML file as CSS div:
<div class="test" ></div>
In the CSS you would put in something like:
.test {
background: url(../navblue.png);
width:280px;
height:40px;
}
.test:hover {
background: url(../navred.png);
width:280px;
height:40px;
}
Now load the page. The first time it will blink and if you delete the cache and load it again, it would blink again, just as would do for all new visitors. So to avoid this, we will generate a sprite. As previously said, there are multiple ways to do that. One is to open up GIMP or Photoshop or any other toolkit and create, in our example, a new background with 280px width and 80px height, 2 times of what each image originally has. Then add both images in this background and line them up vertically. The only thing left is to remove the background color and export image as PNG.
Alternatively you could use a terminal or command line in a combination with ImageMagick. Just make a folder and inside place all images you want in a sprite. Open a terminal, navigate to the folder and execute:
# Note that this will add all the PNG images in the folder in a vertical position
convert *.png -append our_vertical_sprite.png
# To do it horizontally, add + instead of -
convert *.png +append our_horizontal_sprite.png
To return to the exampe above, I have converted the images into a sprite which returned the following image:
However, to make it work, the CSS of the division class needs to be modified:
/* Note that now the sprite is used as background but no offset is used as default */
test {
background: url(../images/nav_sprite.png) 0 0 no-repeat;
width:280px;
height:40px;
}
/* On hover the offset is now -40px vertically */
.test:hover {
background-position: 0 -40px;
width:280px;
height:40px;
}
Now fire up the browser again and try once more. The blinking bug has gone away to bother someone else. ^^
When and how to use Sprites in practice?
Now that you understand the concept of CSS sprites, you could put all the images, an entire layout so to speak, into one sprite image file and tell the CSS what and where to display. However, this is not very practical because when you need to change a specific part or specific image, you would have to edit the whole file and, in some cases, even all the CSS classes that are bound to the file.
So to avoid such calamity, make your plan very carefully. If you are going to use sprites for layout, consider splitting it into separate sprite files for header, for navigation, for footer and so on. Never, ever, use sprites for article images, those might need to be changed one at the time and changed fast. On the other hand, use sprites whenever you expect another HTTP request without actually redirecting to another url, for example, as shown above, whenever an image hover effect is in place.
Another thing I would like to mention is that you should NOT generate a sprite of more than 10 images either horizontally or vertically. It's just not very practical. Instead do it in a matrix like pattern. To extend our example I'll add two more images to show you an example:
Now instead of appending them vertically or horizontally, we'll execute the following command to achieve a 2x2 matrix with ImageMagick
montage *.png -tile 2x -geometry +0 result.png
The command outputs the following sprite image.
For more information on how to use ImageMagick, you can read the manual here. Or you can do it via GIMP or Photoshop or other toolkits. Now that you know why, when and how, the design and its execution solely depends on your imagination.