Use data URI's in CSS across all browsers, even in IE < 8

What are data URI's and why you should use them?

Data URI's provide the ability to embed data directly into a document (for example: HTML pages, CSS, ...) without referencing to an external source.

This make it possible to embed images directly into a stylesheet, and you get one single file which is responsible for the look of a website.

Data URI's are a perfect way to reduce the HTTP requests on a website. Reducing the number of HTTP requests is the key to get faster websites.

The problem with Internet Explorer < 8

Unfortunately Internet Explorer < 8 doesn't support data URI's, but there ist a way to use them anyway. Stoyan Stefanov describes how that works with MHTML. Please read the article from Stoyan first before you continue here.

In Stoyan's example the MHTML data is directly embedded into the main stylesheet, like this:
/*
Content-Type: multipart/related; boundary="_ANY_SEPARATOR"

--_ANY_SEPARATOR
Content-Location:somekey
Content-Transfer-Encoding:base64

iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAA[...]SuQmCC
*/

#someId {
  /* normal browsers */
  background-image: url("data:image/png;base64,iVBORw0[...]");
  /* IE < 8 targeted with the star hack */
  *background-image: url(mhtml:http://www.betalon.com/style.css!somekey);
}

With this method all browsers which are supporting data URI's also have to download the MHTML data, although they don't need them.

So I tried to put the MHTML data into an external file, an reference to it in the main CSS file. And it works!

Important is that the external MHTML file is delivered by the webserver as text/plain, because of the security model in IE7 running under Windows Vista.

With this solution the CSS would look like this:
/* content of style.css */
#someId {
  /* normal browsers */
  background-image: url("data:image/png;base64,iVBORw0[...]");
  /* IE < 8 targeted with the star hack */
  *background-image: url(mhtml:http://www.betalon.com/style.iecss!somekey);
}

And this is the content of the style.iecss:
/*
Content-Type: multipart/related; boundary="_ANY_SEPARATOR"

--_ANY_SEPARATOR
Content-Location:somekey
Content-Transfer-Encoding:base64

iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAIAA[...]SuQmCC
*/

And how to create this files?

Sure, it would be very complex and expensive to create this files yourself, so there must be an automated way. I've written a little filter for Phing (a build system for PHP). This filter reads a traditional CSS file, with referenced images and replace them with data URI's, and insert the hack for IE < 8. It also creates the MHTML document which is referenced in the CSS hack for IE < 8, with the same filename as the source CSS but the file extension is .iecss.

With this solution the useage of data URI's is very simple, because you don't have to care about them :)

Note:
If you want to use data URI's in a live environment please be sure you use gzip compression for your css files, to reduce the filesize.

See it in action:
I use this solution for this website, feel free to discover my CSS sources, you can also compare the differences:

With data URI's: http://www.betalon.com/
Without data URI's: http://www.betalon.com/?debug=1

Leave a comment

Paul Dec 24, 2009 10:44:00 PM
I haven\'t tried this out yet (or read this page as I came here from somewhere else and have already proved it works on another of your pages), but I see from this page that it works. Have been trying to solve this for a long time.

So thank you very much. Much appreciated!

Look forward to learning more from your site -- and this page when I get around to reading it :o)
Paul Dec 24, 2009 11:34:14 PM
Well, I should have read the page!

What I am actually thanking you for (though this is good too) is the ability to embed an image in CSS, such as you are doing on this page) that works cross browser.

Now I can modify my off-line page to work in IE. So, thanks again.

Happy holidays!
Binod Pant Feb 5, 2010 7:19:16 PM
How do I do this for a single file? If I do not want to generate a separate CSS File?
Russel May 21, 2010 12:38:47 PM
I don\'t get it, where is \"phing.filters.CssEmbedBase64Image\"? Where can I download it to try?
Russel May 21, 2010 12:38:47 PM
I don\'t get it, where is \"phing.filters.CssEmbedBase64Image\"? Where can I download it to try?