The Art of Creating CSS Sprites

Depending on how deep your pockets are, bandwidth may or may not be a precious commodity. However, lowering HTTP-Requests will always be the web optimizer’s version of The One Ring. Tenni Theurer of the YUI blog has more to say about the topic but the gist of it is, the less requests your users have to make for an asset, the faster your page will load.

So what is a CSS sprite?

Remember how cool it was back in the ’80s watching Mario run around murdering everything in his path with fireballs on the way to save the princess who, for some reason, lacked a royal guard? Those animations were done using sprites. That is, individual states of a picture on a mapped image. A more web-related example is hovering your mouse over an image button and having a rollover effect, such as with our customize button. Below you can see the customize button in action and an example of what the sprite image file would look like:

Using CSS, we can make the button look and react the way we want it to.

Great! But how?

Let’s use the above example as a reference. The width dimensions of the image are 106px. The height of each individual button sprite is 25px. Yes, the image file itself is 50px in height, but that’s because it’s looking at both sprites on top of one another and aggregating their height. We just want one, because that’s all we’re mapping. The CSS is as follows:

<code> a.customize_button { background: url(..images/sprite.png) 0 0 no-repeat; height: 25px; width: 106px; display: block; } a.customize_button:hover { background-position: left bottom; } </code>

What we’re doing here is setting the element to use the image as its background and specifying the dimensions of the element to be the size of the sprite in question. When hovered, we change the position of the background to then show the next sprite.

That sounds good, how far can I take this?

This technique can be applied to anything defined via CSS. Icons, borders, frames, backgrounds, and with some trickery even repeating background images. Repeating background images can only repeat in one dimension to work with this technique because of apparent limitations in the way our universe is structured (i.e. logic), so you would need one sprite file for all x-repeating sprites of the same height and one sprite file for all y-repeating sprites of the same width. At any rate, the savings on requests can be potentially huge.

When you have various sprites in one file, you use the background-position property to specify the boundaries of the sprite in relation to the file, and width and height for the proper size. That’s essentially what we did in the example above. Granted, it gets progressively more complicated the more files you add, but sometimes you need to play the game in hard mode if you want better results.

Looking at one of our sprite files, we can see a big impact:

Number of requests: 1
Total file size: 70kb

If we were to keep those as individual images, it would look more like this:

Number of requests: 13
Total file size: 76kb

Using one file, we manage to save 12 requests and 6kb. The 6kb may not be notable, but the 12 requests sure is. Carry this over all of your files across your stylesheets and you’re looking at dozens or maybe even hundreds of saved requests! All the cool kids are doing it. Even Facebook.