At the end of my last post on base64 encoding I wanted to see how numbers changed when using a large image sprite and also how page speed was affected.
To do this I decided to work with one Google’s larger image sprites nav_logo107.png
And to focus the test I removed 2 of the previous test cases (the individual binary images and split base64 encodes) as it was clear from the first post that they would not be small enough to compete.
So that leaves a pure binary sprite and a sprite encoded as base64 for which I created 2 test pages:
First: File Size
The good news is that results from my previous post were still true.
If we set the baseline that the delivered css for both cases is minified and gzipped then both end up being almost exactly the same overall byte size.
Second: Page Speed
To check page speed I ran 3 sets of tests using webpagetest.org:
- Dulles, VA / Chrome / DSL
sprite.html – http://www.webpagetest.org/result/120412_A5_3YAXN/
b64-sprite.html – http://www.webpagetest.org/result/120412_DZ_3YAXS/
- Dulles, VA / IE8 / DSL
sprite.html – http://www.webpagetest.org/result/120412_F1_3YAXE/
b64-sprite.html – http://www.webpagetest.org/result/120412_KX_3YAXG/
- Dulles VA / IE9 / DSL
sprite.html – http://www.webpagetest.org/result/120412_EW_3YAY1/
b64-sprite.html – http://www.webpagetest.org/result/120412_CS_3YAY3/
Each test was run 5 times for both First View (no cache) and Repeat View (cache)
My initial thought was that the base64 encoded sprite would be faster (as it would be 1 less request)… and it is when looking at total page load time.
In most tests b64-sprite.html total page load time was around 200ms faster without the additional image request.
So if we were only looking at total load time then we have a clear winner.
But take a moment and look at start render times in those same tests.
On “First View” tests sprite.html has start render times that are around 200ms to 300ms faster in each comparison.
You can see what this translates to visually in this video:http://www.webpagetest.org/video/view.php?id=120412_5129cebbfde1452b10358afa3a1f5dacd106366d
Have you ever heard a user say the phrase “this page feels slow”?
I find that in most cases when questioned further the feeling of slowness was due to the time they were waiting for something (anything) to render to the screen.
This is important to keep in mind when deciding if base64 encoding sprites will make sense for your site.
Yes you are saving a request (which will reduce total load time) but you are also making your css files larger (which could increase start render time).
Even in “Repeat View” where resources are cached locally the start render times for sprite.html are faster. Yes I know we are talking about 10s of milliseconds but try to think of this on a full production site with lots of other resources. Remember even though the css is cached locally the browser still needs to pull it from local cache and render it. So if the cached file is larger in size it will take longer to render.
As an aside: IE8 throws a nice wrench into the gears on this as well. IE8 only supports data URIs up to 32k in size. So if you plan to base64 encode large image sprites you will run into issues with IE8 (basically they won’t render at all in that version).
I hate to say this but when choosing which option is best it will depend mostly on the project.
I would ask the following questions if you are using a large image sprite:
1) Are start render times more important than overall load time for your users? If yes then based on the above findings it would make sense to try the image in pure binary first and run speed tests.
2) Do you still support IE8? If yes then go with a pure binary sprite.
3) Do you plan to set expires headers the same on css and images? If no then consider a pure binary sprite. That way when a user’s local cache is cleared on your css they won’t have to download a larger file each time.
Thank you for reading and please let me know your thoughts in the comments below
A good friend introduced me to the concept base64 encoding and I have gone down the road to research what scenarios it is best suited for.
On that road I found a great post by David Calhoun testing byte sizes by comparing binary images to their base64 counterparts. After reading it I thought it would be interesting to extend his UI icon test one step further and include an image sprite to see how that compares in byte size.
Note: I understand the drawbacks David has mentioned regarding sprites however I believe those drawbacks are manageable considering the potential gains to be had from a file size standpoint. Especially if you are managing more than just icons in your sprite files.
How I setup the test:
- Created a single sprite image from the 5 icons used in David’s initial test
- Created 4 test cases…
- image calls separated out for a total of 6 requests (1 CSS + 5 Images)
- 1 image call to a combined sprite image for a total of 2 requests (1 CSS + 1 Image)
- a file similar to split-binaries.css but instead use base64 for each image for a total of 1 request (1 CSS)
- a file similar to combined-binary.css but instead use base64 for the sprite image for a total of 1 request (1 CSS)
- Gzipped each CSS File and Image to get Gzipped byte sizes
- Minified each CSS File as I would on production
- Calculated total byte size from the combination of images + css needed for each case
So lets see how the numbers work out…
What I thought I would see:
- Test Case#2 (icon-sprite.png + combined-binary.css) would be the smallest in total filesize when compared to Test Case #1 (split-binaries.css plus its images) and Test Case #3 (split-b64.css)
- Test Case#4 (combined-b64.css – which replaces the image sprite with its base64 counterpart) would be the smallest total file size after Gzipping was done
- Gzipping Binary Images would sometimes lead to larger filesizes as those binaries would typically be compressed fairly well to begin with (or at least should be if you care about responsiveness)
- View on Google Docs
- assumption #1 turned out true. The creation of a sprite from the 5 icon images was smaller in file size than both separate images and separate base64 encodes.
- assumption #2 did not turn out to be true. However it was by such a small amount that you could pretty much say it is equal to Test Case #2 (we are talking about 23 bytes here)
- assumption #3 was interesting as gzipping of the binary spite resulted in a slightly larger filesize but gzipping the images individually ended up being smaller in total size. The differences are pretty tiny anyway and because of potential overhead in the gzip process this would probably not be needed if you are good about optimizing your source images.
So what does this really mean?
I think the numbers above depend on what you prefer to use and how you like to work. To be transparent I have always preferred image sprites. My opinion is managing them becomes easier the more you use them and there are a lot of good techniques today to get around some of their earlier drawbacks (such as using pseudo selectors to help get over clipping issues). So considering the findings above I personally would probably continue to stick with sprites.
However… you could possibly get benefit by making a sprite, converting to it base64 and then gziping it. The gain here would be 1 less request (and that could mean a lot on a larger site). To really test this idea I am going to build a case using a larger sprite file that has more than just icons in it to see how it scales.
In the future I am going to try to run performance testing to see baseline speed for each case from different locations (I’ll use webpagetest.org). Number of requests can sometimes make a huge difference in those tests so that might help put some additional clarity around this topic as well.
Further reading on base64: