Today, I’m writing about a topic I personally know little about, but I’ve heard experts mention it in passing for years. I couldn’t find any good references, hence the post below.
The first rule for building high performance web sites is to make fewer requests, and using CSS sprites is one key and commonly-deployed means of doing so. Unfortunately, however, some websites are trading one performance problem (too many requests) for another problem (increased memory load on the client).
The first problem is that some designers treat “empty space” inside sprite images as “free,” because empty areas compress so well that the file size doesn’t grow. As a consequence, they may generate images that are 50% empty or worse. The problem is that the client ultimately still needs to allocate memory for those regions when the image is decompressed for rendering. So, don’t leave large gaps in your sprite collections. You should leave a little padding between the sprites in the image, however, because if the sprites aren’t padded at all, and the user has zoomed the website, a GPU may sample adjacent pixels when rendering the scaled sprite.
Surprisingly, the shape of your sprite image matters as well. Consider Facebook’s primary sprite image. It’s 26 pixels wide and 8227 pixels tall, and uses 32bit color. To optimize performance and memory consumption on the client, sprite collection images should be square(ish) and their dimensions should be a power of 2; this image would consume less memory on the system and GPU if it were instead 512×512 pixels.
Note that further network optimization is available: If I use RIOT Optimizer to convert Facebook’s image to use an optimal 256 color palette, the image shrinks from 143kb to 60kb; I couldn’t see any visual differences.
You can easily find un-optimized sprite images with Fiddler. To add an Image Dimensions column to Fiddler’s UI, right-click the column headers, choose Customize Columns, and add the column like so:
Bonus Tip: When using JPEG (for images on your site), you should use Progressive format and 4:2:0 or 4:2:2 chroma subsampling to improve size and optimize memory usage. Fiddler’s ImageView inspector will tell you what chroma subsampling was used and whether or not a JPEG is Progressive.