Data URIs

Chris Coyier //

Did you know that you don't have to link to an external image file when using an <img> element in HTML, or declaring a background-image in CSS? You can embed the image data directly into the document with data URIs.

With CSS, it looks like this:

li {
  background:
    url(data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7)
    no-repeat
    left center;
  padding: 5px 0 5px 25px;
}

With HTML, it looks like this:

<img width="16" height="16" alt="star" src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" />

The format, to be specific:

data:[<mime type>][;charset=<charset>][;base64],<encoded data>

Basically, a super long string of gibberish characters. It's not gibberish to the browser though of course. This data is interpreted as the type of file you are saying it is.

You can see a really dumb demo page here. I'll be covering the important parts next.

Why would you do this?

The biggest reason: it saves HTTP Requests. Other than pure document size, this is the #1 factor concerning how fast a page loads. Less = better.

How do you get the code?

Use this online conversion tool. It's the nicest one I have found. Here's a drag and drop one.

Also note that base64 isn't the only possible format for a data URI and sometimes it isn't even a good idea. ASCII is another, where the code is essentially URL encoded, or UTF-8.

Browser Compatibility

Data URI's don't work in IE 5-7, but are supported in IE 8. You could:

  • Use an IE-only stylesheet to put images in, or,
  • Use it only for progressive enhancement type stuff where having no image is perfectly acceptable, or,
  • Not care
  • Read this article about an alternate technique that does work.

Important Notes

  • Size of embedded code is somewhat larger than size of resource by itself. GZip compression will help.
  • IE8 has the lowest maximum data URI size of 32768 Bytes. (HEY?!?! There is that crazy number again.)
  • It's hard to maintain site with embedded data URIs for everything. It's easier to just update an image and replace it.
  • If you are using PHP (or PHP as CSS), you could create data URIs on the fly like this:
    <?php
      echo base64_encode(file_get_contents("../images/folder16.gif"))
    ?>
  • You should only use this in documents that are heavily cached, like your CSS should be. Having a CSS file that is 300k instead of 50k is fine if it saves 6 HTTP requests, but only if that CSS file is cached just as well as those images would be. Setting long expires on CSS files should help.
  • Data URIs are not limited to images, they could literally be anything.
  • <canvas> may obsolete the coolness of all this, when it gets more supported and people build cool tools for it.
  • Compass has a helper.

On Performance

Some relevant research by Peter McLachlan:

...when measuring the performance of hundreds of thousands of mobile page views, that loading images using a data URI is on average 6x slower than using a binary source link such as an img tag with an src attribute!