A Quick Examination of the Memory and Perfomance Ramifications of CSS Sprite Dimensions

I recently ran into an interesting CSS Sprite. It contains what appears to be all of a web app’s site’s icons. What was interesting was the fact that it’s a 32 Bit PNG at 1500 x 1500 pixels- many of which are empty. Here’s what it looks like shrunk down for easy consumption and the empty space colored pink for emphasis.

As you can see there’s an awful lot of empty space. It’s mostly empty space. Between the huge dimensions and the empty space at how they would affect memory usage and front end performance.

I did a couple of tests. One was looking at the memory footprint of five sample pages in Chrome and the other was measuring download times with WebPageTest.

I’ll go through each of the variations I tried and then we’ll look at the results.

Won’t that be fun?

Baseline

There were really two "baselines." The first is a page with just an LI and no styling. The second is an approximation of the way the sprite is used on the site. It’s the same structure as before (LI, with nested SPANs,) with the addition of styles for the icons. Adding the icons to the mix increased the file load time by over a second and increased the memory load on the page in Chrome by 10 MB.

Here’s what it looks like.

File Cropped and Roughly Edited to Remove Empty Space

My first attempt was to simply edit the file down, keeping the same spacing between the icons, but removing most of the empty space.

Here’s what that file looks like. Again, shrunk down from its original 800px width and with the pink representing the empty space.

Just doing this improved things significantly, cutting the memory used in half (by reducing, significantly, the number of pixels) and lowering the download time by nearly 1/2 second (owing to the drop in file size.)

That was the quick and dirty approach. There are two superior approaches. Which path you take depends on the nature of your site and the way people access it.

Icons Split Across Several Sprites

For this version the idea was to split the large icon file into several smaller spites. In a real site they’d be organized by, for example, site section. The approach is to have just enough icons to render the main page. The next icons could be loaded on an as needed basis or preloaded in the background. This has the benefit of having a much smaller file size, which speeds things up over the wire. Here’s what that file looks like (full size:)

The downside is that you have to connect to the server and download several different files over the course of the user’s visit. All of those connections would slow down the overall performance of the site as each download brings with it its own performance penalty.

That said, as the numbers show, if you’re looking to optimize the first page view versus over the general site or application experience, then this is the way to go. It’s 1/2 second faster than any other version.

Optimized Sprite

This is the version that optimizes for the overall site experience. The space between the icons is cut down to a minimum, but they’re all present. Here’s what that one looks like. Yes, more pink and shrunk down (although this one has been shrunk only by about 1/2- compare that to the 1/8th the original sprite was shrunk to get it on the page.)

It’s larger and slower than the cropped version, but would be cached immediately and the rest of the site would load that much faster. Interestingly, because it’s so compact, the memory footprint is tiny, nearly the equal of the cropped image.

Here are the results (by the numbers):

Name Private Shared Total WebpageTest Time File Size Dimensions
no icons 2520k 6788k 9308k 0.613s NA  
original sprite 11500k 6936k 18436k 1.850s 85KB 1500 x 1500
blank space stripped 5832k 6984k 12816k 1.367s 50KB 818 x 966
cropped file 2872k 6948k 9820k 0.870s 6KB 316 x 227
optimized sprite 3384k 7000k 10384k 1.385s 42KB 455 x 413

Takeaways

  • Stay away from empty space in CSS Sprites- especially when using 24 Bit PNGs or JPGs. Use your space efficiently. Empty space might compress well, but those pixels count when the browser actually gets down to using the file.
  • Stay away from large sprites. Whatever the size the file is over the wire, the dimensions are going play a role in the memory footprint.
  • Optimize for your needs.
    • If the most important page on your site is a signup form that you funnel people to through campaigns, the optimize the hell out of that one page, only loading the bare minimum needed to render it correctly. Keep the number of files down, as always, but also keep an eye towards the size over the wire..
    • If you get people coming in from all corners and count on people quickly moving through pages or parts of an application you might want to optimize for the full site experience by maybe loading a larger sprite file that deals with a broader cross-section of the site experience.

2 thoughts on “A Quick Examination of the Memory and Perfomance Ramifications of CSS Sprite Dimensions

  1. Cross posting from a comment on my blog that you commented on so that you will see it 🙂

    Very interesting read.

    I’m in no way trying to downplay your findings, but in looking at your table of results it seems that the memory used semi tracks with the addition of filesize. Is the additional memory used related to the dimensions of the image or to the filesize?

    Meaning if you had one file that was 1000×1000 and 10k, and you had another file that was more complicated and was 100×100 and 10k, would the memory usage be the same for both, or higher for the file with the larger dimensions. If higher, is it significantly higher, or just a little bit?

    Also, what is the real impact of this for the user? In this day of multiple gigabytes of memory available, does a few extra K of memory have much effect? Is memory used for images reallocated well (as opposed to JS that has memory leaks and stuff)?

    Again, not trying to diminish your findings at all. The thought of memory use hadn’t entered my mind at all and these are just things I wonder about as a result.

    I am a major advocate for performance at my work. So if this truly is a performance hit, I would be the first to stop using it.

    Although I would guess that for smaller sprites, say 10 components or so, that are running into the situation this fixes (accidentally showing additional components) the memory cost is negligible and so this is still a viable solution.

  2. I don’t have great answers to your questions, to be honest, at least to the correlation between file size, complexity, pixels and memory footprint. It deserves a further look. As I mentioned this is a quick and dirty look based on a sprite I was actually presented with in an application. I could structure a test pretty simply (photographic image versus a two or three color pattern versus a one color image, for example)

    On the other side, I do know that I don’t ever assume “gigabytes of memory” when planning my approach to a site build. There are a lot of crappy computers out there, and there are going to continue to be a lot of crappy computers out there, so I don’t ever assume the best when it comes to my user’s hardware. I assume the worst, because if I can present at least a halfway decent experience on a machine with 500MB of RAM, then it’s going to kick ass on a newer machine.

    And that’s completely ignoring mobile, where the limitations are pretty severe.

    It’s from that perspective that this post, my comment on your technique (which, beyond my comment about the 1500 x 1500 example is completely viable) and my general concern for sprite dimensions comes into play.

Leave a Reply

Your email address will not be published. Required fields are marked *