One of my colleagues recently forwarded this slide presentation about Mobile Web Performance that he saw at the Velocity Conference. I'm leading a large mobile web project at our company, which conveniently enough, we were just discussing the need for sprite maps to reduce the number of requests.
So taking one of my engineer's suggestion and the above presentation I learned about Data URI Scheme, which is a way to use encoded data sent to the browser as text instead of a separate file, such as an image file.
Here's an example of a simple red square:
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRF/wAAAAAAQaMSAwAAABJJREFUeNpiYBgFo2AwAIAAAwACigABtnCV2AAAAABJRU5ErkJggg==
You can display directly by putting that in an IMG tag:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAMAAADzN3VRAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAAZQTFRF/wAAAAAAQaMSAwAAABJJREFUeNpiYBgFo2AwAIAAAwACigABtnCV2AAAAABJRU5ErkJggg=="/>
In a browser, it shows like so (no external file needed):
You should see a "red square" image above, assuming you are using Firefox, Safari or Chrome. Unfortunately, IE7 does not work; IE8 claims some support, but I did not have any luck with my testing.
So once again our cool new fancy technique can't be used because of browser support, right? Wrong, IE is a fraction of the mobile web market. It is dominated by webkit browsers, which do support it. Particularly nice since mobile is an area where every requests makes a difference, considering the spotty networks and under powered phones (compared to a desktop browser)
Now, you don't necessarily want to include the data in an HTML file, because you won't get the benefit of caching. Here's an example of the Data URI Scheme used within CSS:
.red_square {
background url('data:image/png;base64,[encoding]');
width: 25; height: 25;
}
Replacing [encoding] with the large string, no line breaks or spaces, but keep the quotes. Than any where you want to use that image, just reference the CSS;
<div class="red_square"/></div>
You can collect up similar and common items that you might of previously put in a sprite map in a single css file. If you use a CDN, such as Akamai, or even just using the browser cache, you'll end of delivering multiple images in a single request which can be cached.
Using the Data URI Scheme it is easy to update a single image, which in a sprite map could be tricky. Also it simplifies the reference of the images without requiring a more complex coordinate selection of images which is typically done in CSS sprites.
There are a few ways to encode a file to base64, there is a unix program aptly called *base64** which is what I use; I installed using MacPorts, on Ubuntu you can install with a simple apt-get. If those don't work for you, you can try an online base64 generator.
To encode:
$ base64 red_square.png
It will spit out the encoded string, you'll have to remove any line breaks that get included. If you are on a Mac, there a couple of nice clipboard unix tools that make it even easier. You can pipe output into pbcopy which will place the output in your clipboard buffer. Ready to be pasted in.
$ base64 red_square.png | pbcopy
The base64 utility can also decode a string back to the original file. To do that save the encoded string to a file such as encoded.txt and run base64 with the --decode parameter, like so
$ base64 --decode encoded.txt >red_square_decoded.png
This makes it easy to "recover" the original images if all you had was the CSS files.
I think this is a great technique to reduce complexity for accessing images and provide greater performance to our mobile users. We've already started implementing across our mobile sites.
Mobile Web Performance presentation by Maximiliano Firtman
Data URI Scheme (Wikipedia)
Online Base64 Generator (MobileFish)