Optimizing Sprites

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:

Fiddler's AddColumn UI

-Eric Lawrence

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.

Comments (4)

  1. sorrybi@hotmail.com says:

    As far as I recall, progressive JPEG has either rendering performance issues (and maybe mobile device support issues), or file size costs, so I would not recommend using this.

    [EricLaw] You misremember. Progressive JPEGs are typically smaller than their non-progressive counterparts; this counter-intuitive finding made quite a splash back in 2012 when it was seriously studied. As for "device support issues"– this typically only concerns whether the device renders a progressive JPEG progressively or not; if it renders non-progressively, there's no real harm.

  2. sorrybi@hotmail.com says:

    Also, do you know whether the square and power of 2 rules are applicable to all of the browsers?

    [EricLaw] This is more a function of the graphics hardware and pipeline than the browser in use; browsers that aren't hardware-accelerated obviously won't benefit from such optimizations, but aren't harmed by them either.

  3. sorrybi@hotmail.com says:

    do you happen to know whether it takes more CPU cycles to decode a progressive JPEG?

    [EricLaw] It can, yes; there's a discussion of this here: http://calendar.perfplanet.com/2012/progressive-jpegs-a-new-best-practice/. Mobile clients may decline to render progressively for this reason, although with hardware acceleration the CPU costs are decreasingly relevant.

  4. ddj says:

    Whats the reason behind squareish images being more performant? I had not heard this one before.

    [EricLaw] With again the caveat that I'm not an expert on this, my recollection from the folks who are is that some drivers/graphics hardware will effectively end up padding out allocations for such images to a square shape for performance reasons.