ANS 1001 untold stories

The one and only correct way to use sprites.

In this post I'll show you the one and only correct way to use sprites and the very little benefit if you use sprites the wrong way.

It's in everyones mouth but a lot of people do not understand fully what sprites are supposed to optimize. Well we want so badly to reduce the HTTP requests but as I'll show you, a lot of people do not understand how to write efficient selectors for sprites.

Here's a meaningfull chart I'm going to explain a few pixel down.
css sprites the wrong and correct way

The first "wrong way" uses multiple images and no sprites and show you what you might except. For each image a request gets done. 22ms were used.

The second wrong way shows you something, a lot of people wouldn't have guessed. For each CSS selector a request is made! The reason is, that the Browser does not know that the image has been already requested and requests it again. The browser then, when it does it's pre-processing understands, that tghe ressource has been already requested and grabs it ideally from the browser-cache. However that's just 4ms faster than without sprites.

  
.icon-mail             { background: transparent url(images/sprite.png) 0 0 no-repeat }
.icon-mail-add         { background: transparent url(images/sprite.png) 0 -40px no-repeat }
.icon-mail-attach         { background: transparent url(images/sprite.png) 0 -80px no-repeat }
.icon-mail-delete         { background: transparent url(images/sprite.png) 0 -120px no-repeat }
.icon-mail-edit         { background: transparent url(images/sprite.png) 0 -160px no-repeat }
.icon-mail-error         { background: transparent url(images/sprite.png) 0 -200px no-repeat }
.icon-mail-go             { background: transparent url(images/sprite.png) 0 -240px no-repeat }
.icon-mail-link         { background: transparent url(images/sprite.png) 0 -280px no-repeat }
.icon-nail-open         { background: transparent url(images/sprite.png) 0 -320px no-repeat }
.icon-mail-open-image     { background: transparent url(images/sprite.png) 0 -360px no-repeat }

The third and correct way uses one selector containing the sprite and a few others to change only the position of the sprite. As you can see in my fancy chart, the benefit is: 4ms for the whole test document. Thats 5.5 times faster than the first example and unbelievable 4 times faster than the second example, which uses the very same sprite!

  
.icons { background-image: url(images/sprite.png); background-repeat: none }
.icon-mail             { background-position: 0 0 }
.icon-mail-add         { background-position: 0 -40px }
.icon-mail-attach         { background-position: 0 -80px }
.icon-mail-delete         { background-position: 0 -120px }
.icon-mail-edit         { background-position: 0 -160px }
.icon-mail-error         { background-position: 0 -200px }
.icon-mail-go             { background-position: 0 -240px }
.icon-mail-link         { background-position: 0 -280px }
.icon-nail-open         { background-position: 0 -320px }
.icon-mail-open-image     { background-position: 0 -360px }

ps: You need something like firebug or httpwatch to check it for yourself.