Grow your CSS skills. Land your dream job.

Data URIs

Published by 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.

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!

Comments

  1. Jason Zhekov
    Permalink to comment#

    “Having a CSS file that is 300k instead of 50k is fine if it saves 6 HTTP requests.” Well it saves 6 requests and the page will load faster, but the user will have to wate the css to be downloaded to see some visual feedback.

  2. That’s pretty cool. If you were using PHP as noted above you could probably write a pretty quick function that would check what browser is being used (i.e. IE6) and then make the decision to encode the filepath or use regular img tag.

    • That sounds like a pretty good idea, you can have the css parsed by php first, then check the browser and depending on it throw the data or the url of the image.

      That combined with cache should be a really good way to go…

  3. Permalink to comment#

    I like this thing. Thanks!

  4. This can be really useful if you ever create a single-page web document that you email to people rather than uploading to a server. The best example of this I have would be a resume, or something similar.

    I’ve used this before, and it saves the hassle of having to send a bunch of files for that single document. Instead you just send “my-resume.html” and you are done.

    If you wanted to use it on a live website, I’d only recommend it for very small images (i.e. list bullets), since as seen in the example Jason Zhekov posted, it can create very large load times.

  5. Leonardo
    Permalink to comment#

    Your arguments are no doubt valid but
    images/pretty-flower.jpg or images/me-after-way-too-much-beer.jpg is much clearer when I have toc go throuh the code…

    • “I have toc go throuh the code” – some typos there – trying to tell us something with the me-after-way-too-much-beer image haha?

    • LordRegent
      Permalink to comment#

      This W3C specification states that img elements should always be given an alt attribute, along with a list of when the attribute “must” be given a value. When used as you describe, the alternative text should not be blank, which would make it easy to both document and later determine the image’s content.

  6. Dave Scarlatella
    Permalink to comment#

    It’s interesting that this popped up in my RSS feed today. I was just weighing the options of using data uri for photo in hcards.

  7. This is very useful for small images, e.g. icons, for mobile versions of pages

  8. Permalink to comment#

    You should only use this for elements on every page or the most used pages. If you don’t, users will load the “images” even when they don’t have to.

  9. Permalink to comment#

    For further explanation on data URIs, check out this page: http://www.nczonline.net/blog/2009/10/27/data-uris-explained/

  10. I honestly can say I did not know this was possible. With the speed of the web today and with an already well designed and coded design surely this is not necessary. Maybe I am ignorant but can’t see how in reality this will make much difference.

    Fair enough though for implementing it and showing us how it works. Always amaze me with your coding.

    Thanks.

  11. Permalink to comment#

    if this was good it would be common practice

  12. Permalink to comment#

    David Desandro has a great tool for creating Data URIs with the <canvas> element. He recommends using the canvas to generate graphics procedurally, and then plugging the URI straight into CSS. This is great for prototyping if you’re handy with graphics programming.

  13. Yannick
    Permalink to comment#

    What about cache? When you refer to an image this is loaded once, and whenever you browse in that site you are loading the image from the cache. When you “hardcode” it in html it is loaded every time… (much more trafic and slower)

    • Permalink to comment#

      Ideally, you’d be hardcoding this into an external stylesheet, not HTML, so it would still get cached.

  14. Yep, data uris are great. I use it when developing iPhone web apps. It’s specially useful in that situation, since you don’t have to worry about IE, and makes handling the app caching easier.

  15. Permalink to comment#

    Can data URIs be used in CSS sprite image? How to do that?

  16. I wonder if this is how Apple sends me HTML emails that show the images without issue when other companies I have to “click to approve” images.

    • Good question! That is absolutely worth exploring.

    • That’s got to be it. I’ve always wondered how they do that and, more importantly, why other companies don’t do the same thing.

    • Akshay Aurora
      Permalink to comment#

      I received a mail from Apple today, and it asked for approval of images….

    • Miro von Busing
      Permalink to comment#

      When creating an html-mail you may choose to embed the images or not. The pros for embedding is that your mail will (probably) display as you expected. The cons is a larger email, which may be an issue if you are sending a zillion email. Also you miss the track-back opportunity when the email client requests the pictures on your server.

      @andy: probably, you have once approved that it is “safe” to download images from Apples servers and your email client remembers that.

    • Rob Y
      Permalink to comment#

      This looks MUCH easier than referencing MIME attachments for embedded images.

      If you check out the source of an e-mail with embedded images it looks something like this:

      and then later, the image is a mime attachment with the matching id


      ------=_NextPart_000_02A7_01CAC9B2.32C8E9F0
      Content-Type: image/jpeg;
      name="image002.jpg"
      Content-Transfer-Encoding: base64
      Content-ID:

      /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIf...

      (this was generated by Thunderbird, obviously you can use simpler cid values)

      This method will deliver image rich emails without requiring the user to click “show images”, but it is a pain to do manually. If you are writing an order confirmation script, for example, and you want the company logo and background image to make the receipt look nice, this method looks MUCH simpler than building the MIME attachments.

      Thanks for the “trick” Chris!

    • Rob Y
      Permalink to comment#

      This looks MUCH easier than referencing MIME attachments for embedded images.

      If you check out the source of an e-mail with embedded images it looks something like this:

      <code>
      <img width=3D703 height=3D413 =
      id=3D”Picture_x0020_10″
      src=3D”cid:image002.jpg@01CAC9B2.3080CEB0″>
      </code>

      and then later, the image is a mime attachment with the matching id

      <code>
      ——=_NextPart_000_02A7_01CAC9B2.32C8E9F0
      Content-Type: image/jpeg;
      name=”image002.jpg”
      Content-Transfer-Encoding: base64
      Content-ID: <image002.jpg@01CAC9B2.3080CEB0>

      /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIf…
      </code>

      (this was generated by Thunderbird, obviously you can use simpler cid values)

      This method will deliver image rich emails without requiring the user to click “show images”, but it is a pain to do manually. If you are writing an order confirmation script, for example, and you want the company logo and background image to make the receipt look nice, this method looks MUCH simpler than building the MIME attachments.

      Thanks for the “trick” Chris!

    • What a great point, I have to try this out now.

    • Well, sort of that but not exactly.

      Basically, all E-mail attachments, including images, have a header, that indicates things like the Content Type, length, charset (ASCII, UTF-8 or some obsolete charset) and encoding of the attachment (often base64 for binary files). You can also assign a Content ID to the attachment, which you can reference in your HTML.

      <img src="cid:yourContentId" />

    • Of course, that only works in e-mails and other multipart formats. Your HTML is but yet another attachment in this case. Use of the cid: scheme doesn’t make sense in standalone HTML.

    • You can right click on the images from the Apple e-mails and see if that’s the case.

    • Which brings up another good point… you can’t easily click-and-drag a data URI image off the browser to save it (at least in Firefox) so it’s kind of a rudimentary form of image protection. You can right-click save-as though..

    • You can always disable the right-click mouse button.

    • Isn’t this because they add themselves to your address book on your mac, and images from people in your address book load automatically?

      That’s what I thought… maybe not though.

  17. This technique is used by Google for the mobile version of Gmail, change your user agent to something mobile, e.g. iPhone and goto gmail.com.

    They primarily use it on the Google logo & buzz icon, and this is just one of the tricks used make the amazing single http request mobile Gmail

  18. Permalink to comment#

    Pretty cool! Don’t quote me on this, but I believe this method has some issues with IE and HTTPS requests. For some reason the “some elements on this page are unsecure” dialog pops up if using encoding on images.

    I could be wrong, and it could only be for IE7.

  19. Ulyses
    Permalink to comment#

    1. Semantic content: unimportant then, heh.

    2. SVG – an even better idea than XHTML: get used to use it.

    3. Data URI: why use it when you NOW are advised to externalize CSS and JS?

    If one big file is the answer, then we need to establish a system:

    – develop using paradigms like: external CSS and JS, semantic content and so on.

    - deploy in a java applet-like way: jar, war
    or
    - use tools to combine all that content and deploy a big fat file

    But, this way, we begin to step away from the a marked up and an interpreted language. On the way of embracing a world of dependencies.

    Nah, it’s not K.I.S.S. baby.

  20. Ulyses
    Permalink to comment#

    [...]
    The content of an MHTML file is encoded as if it were an HTML e-mail message, using the MIME type multipart/related. The first part of the file is normally encoded HTML; subsequent parts are additional resources identified by their original URLs and encoded in base64. This format is sometimes referred to as MHT, after the suffix .mht given to such files by default when created by Microsoft Word, Internet Explorer or Opera. MHTML is a proposed standard, circulated in a revised edition in 1999 as RFC 2557.
    [...]
    The .mht format was introduced in 1999 with Internet Explorer 5.[1] Saving in this format allows users to save a web page and its resources as a single MHTML file called a “Web Archive”, where all images and linked files will be saved as a single entity. It may, however, be unable to save certain complex web pages correctly, especially those containing scripts.

  21. Ulyses
    Permalink to comment#

    So back to creating web pages in Word ! Hahaha.

  22. xleo
    Permalink to comment#

    Cool! with Python you can encode as follows:

    import base64
    img = base64.b64encode(open('../images/folder16.gif','rb').read())
  23. Ahmed
    Permalink to comment#

    Well, base64 images do show in IE7 when loaded through a stylesheet (at least for me)

    • Ahmed
      Permalink to comment#

      NVM, I was testing in IE8 with IE7 engine loaded…

    • DN
      Permalink to comment#

      Another good example of IE8 in IE7 mode !== IE7.

    • Ahmed
      Permalink to comment#

      Indeed, I won’t count on it, never agian. IETest == IE7, so it’s good.

      However, for IE7, you can use a PHP script to pass the URI data and get it working. Kinda sucky to a certain point, but it’s better than no solution at all.

  24. The PHP auto-encode technique is very cool, might use it on something one day.

    As for IE, you can create “IE-only divs” in conditional comments for different versions, then in your CSS you can reference both images.

    So something like:
    #IE6 .sel, #IE7 .sel { background: original img; }
    .sel { background: encoded img; }

    • Oh and it’d be a good idea to keep an eye out for specificity, so your IE rules don’t get overrided with the encoded image.

  25. Carlos
    Permalink to comment#

    Nice once!

    :)

    About any kind of Internet Explorer, for me don’t care. I believe the people should stop try make the things working on IE.

    Is just you check the browser statics on w3c. Please, be MAN, study and learn how to say no for the clients.

    Now IE9 looks very nice, finally Microsoft resolved work more together of web-standard.

    Best,

    • TeMc
      Permalink to comment#

      Really ?

      Reminds me of this commercial:

      Let’s first see what IE9 will be in the final release. Don’t get your hopes up.

      And besides, what’s Microsoft trying anyway ?

      Those people that are noobish enough to not upgrade a better non-IE browser, aren’t gonna update to IE9 either.

      Invest in a good browser that has a solid foundation and is known to be good. Such as WebKit-engine in Safari or Chrome.

      Just… get it over with Microsoft, it’s over; get back to work.

  26. William
    Permalink to comment#

    I’m just thinking out loud here, but wouldn’t it be cool to do some sort of if() statements with these? For example, if most of an image is blue, than the background of this page should also be blue, etc. Probably unrealistic, but if there were some sort of interpreter, I could see some really interesting possibilities.

    • Permalink to comment#

      I like the way you think, even if it’s totally unrelated to the subject at hand :)

      Something like that should be possible using canvas and the getImageData() function. You could use it to determine the average color of an image and then set the background to that color. You could even average the colors of every picture in an image gallery, for instance, and then programmatically determine a color scheme that would best compliment it.

      It wouldn’t work in IE, but it might in IE9 if they jump on the canvas wagon.

  27. Permalink to comment#

    Personally, I don’t like it.

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

    #1: It’s ugly. I know that’s not much of a reason and it’s probably pretty silly but I find it ugly and don’t want to dirty up my code like that.
    #2: You are putting content directly into the CSS fiile. Granted it’s not much different from specifying a file (which I guess is also putting content into the css and I don’t see any way around that) but it still bothers me. Again, it’s probably a silly reason but it feels wrong to me.
    #3: We all want our sites to be as fast as possible. I jump through a lot of hoops to improve the speed of my sites. But it’s also possible to take it too far. This is a good technique to know but I’ve always considered it to be overkill.

  28. Permalink to comment#

    I wonder if this would be helpful with developing custom Facebook pages. You have to use their own “FBML” editor with acts like HTML.

  29. Yannick
    Permalink to comment#

    I guess this is usefull for phones (they don’t have a fast connection) and for emails (they don’t allow external images automatically)

    but for normal websites it’s a total overkill

    maybe it’s also ok for protecting your images…so they can’t be copied.

    • Yannick
      Permalink to comment#

      ok apparently they can be copied, but they can’t refer to your site, so you’re site won’t suffer from bandwith problems.

  30. Permalink to comment#

    The main idea here is that the images are automatically cached with the CSS/HTML file, and don’t require another HTTP request.

    Very interesting technique, but I’m pretty sure it’s overkill for normal websites. Internet connection today for the general population is advanced enough to load an image once (and cache it anyway later).

    Might be good for mobile/email websites, where external images might cause problems.

    Don’t forget though, you might lose valuable statistics by not linking images to your host.

  31. Demus
    Permalink to comment#

    It’s nice that new techniques are presented but what about semantics? Isn’t it supposed to be img = image and not the hash?

    I’m not hardcore semantics guy and often try to find easiest way for myself, but code is definitely much more readable with real images than with this hash thing. We should always keep in mind that maybe someday our code will be modified by someone else.

    So no matter how fast pages will load with this TRICK, I still will suggest to use real images.

  32. Ulyses
    Permalink to comment#

    New techniques? From 1999?

  33. Ira Siegel
    Permalink to comment#

    Cool, but man, this is overkill.

  34. Permalink to comment#

    I think I only understood the commas

  35. The technique is cool, but it never caught on (1999) and is thus basically a dead technology. Most probably because everyone worried about buffer overflows and internet viruses. It is supported by only some browsers & e-mail clients.

    If IE8 supports it its nice, but 32K is not going to do much beyond a couple of CSS decorations.

    I came across data url’s a few weeks ago when I needed to convert the output of a Windows ActiveX control into something I could e-mail to customers.

    After a little testing we decided to simply convert the Data URL’s into MIME extensions (dead simple!)

  36. Darrin Robertson
    Permalink to comment#

    I agree. The data encoding is not a good way to maintain your images on your site.

    So, I wrote a utility that opens my css files finds the image references and then base64 encodes them. I then output a myprodversion.css. (I also thow in a bit of minification) (I will intergrate this into my build process one day and maybe a VS plug in)

    The downside is that my css files are big but the great news is that my web servers, (and this should be the norm now in my opinion), compress output to the client browser and text compresses very well while images do not.

    So overall the result is less http request per page, (very good for performance) and a smaller overall download size.

    There are caverts and its not always the first option. But it does work well for me in a site where optimisation of performance was very important.

    • Ulyses
      Permalink to comment#

      Compressing data done by web servers crossed my mind not once.

      I should say, that, in the end, it should be in the protocol stack not in web servers functions.

      That way I think it would be effective and generally aprouved.

      Images thou, are compressed already (unless you use *.bmp :) )

  37. Personally I would have called this Base64 images rather than Data URIs…

    Anyway, I used this technique in creating the markItUp! for Greasemonkey script. There’s no other way to embed images in a Greasemonkey script and I didn’t want to have to host the images (that other people would call when they used the script). Using base 64 images was the perfect answer.

    I’ve yet to use it on a website – I’ve always wondered why it wasn’t used more and wondered if there’s some down side.

  38. Permalink to comment#

    Very nice and simple. I was just looking for something like this

    Thank you for sharing

  39. I built a small utility to create data-uris for a favicon image. http://bit.ly/a9VjTX

  40. For anyone looking for a simple way to embed data URIs into a CSS file automatically, check out http://datauri.net .
    It supports drag and drop, multiple files and automatic CSS generation.

  41. Awesome. That’s really a neat trick and well introduced.

    Thanks.

  42. Jojo Bane
    Permalink to comment#

    Is this better than having sprite images?

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".