Should I embed images as data/base64 in CSS or HTML

To reduce the number requests on the server I have embedded some images (PNG & SVG) as BASE64 directly into the css. (Its automated in the build process)

like this:

background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAFWHRTb2Z0d2FyZQBBZG etc...);

Is this a good practice? Are there some reasons to avoid this? Are there some major browser that don't have data url support?

Bonus question: Does it make sense to do this for the CSS & JS also?


Solution 1:

Is this a good practice? Are there some reasons to avoid this?

It's a good practice usually only for very small CSS images that are going to be used together (like CSS sprites) when IE compatibility doesn't matter, and saving the request is more important than cacheability.

It has a number of notable downsides:

  • Doesn't work at all in IE6 and 7.

  • Works for resources only up to 32k in size in IE8. This is the limit that applies after base64 encoding. In other words, no longer than 32768 characters.

  • It saves a request, but bloats the HTML page instead! And makes images uncacheable. They get loaded every time the containing page or style sheet get loaded.

  • Base64 encoding bloats image sizes by 33%.

  • If served in a gzipped resource, data: images are almost certainly going to be a terrible strain on the server's resources! Images are traditionally very CPU intensive to compress, with very little reduction in size.

Solution 2:

Common answers here seems to suggest this is not needed, for a set of legit reasons. However, all of these seems to neglect modern apps behavior and build process.

It's not impossible (and actually quite easy) to design a simple process that will walk through a folder images and will generate a single CSS with all the images of this folder.

This css will be fully cached and will dramatically reduce round trips to the server, which is as correctly suggest by @MemeDeveloper one of the biggest performance hits.

Sure, It's hack. no doubt. same as sprites are a hack. In perfect world this will not be needed, until then, it's a possible practice if what you need to fix is:

  1. Page with multiple images that are not easily "spritable".
  2. Round trip to servers are an actual bottleneck (think mobile).
  3. speed (to the milliseconds level) is really that important for your use case.
  4. You don't care (as you should, if you want the web to go forward) about IE5 and IE6.

my view.

Solution 3:

It's not a good practice. Some browsers are not supporting data URIs (e.g. IE 6 and 7) or support is limited (e.g. 32KB for IE8).

See also this Wikipedia article for complete details on the Data URI disadvantages:

  • Data URI scheme

Disadvantages

  • Data URIs are not separately cached from their containing documents (e.g. CSS or HTML files) so data is downloaded every time the containing documents are redownloaded.
  • Content must be re-encoded and re-embedded every time a change is made.
  • Internet Explorer through version 7 (approximately 15% of the market as of January 2011), lacks support.
  • Internet Explorer 8 limits data URIs to a maximum length of 32 KB.
  • Data is included as a simple stream, and many processing environments (such as web browsers) may not support using containers (such as multipart/alternative or message/rfc822) to provide greater complexity such as metadata, data compression, or content negotiation.
  • Base64-encoded data URIs are 1/3 larger in size than their binary equivalent. (However, this overhead is reduced to 2-3% if the HTTP server compresses the response using gzip)
  • Data URIs make it more difficult for security software to filter content.

Solution 4:

I was using data-uri's for about a month, and Ive just stopped using them because they made my stylesheets absolutely enormous.

Data-uri's do work in IE6/7 (you just need to serve an mhtml file to those browsers).

The one benefit I got from using data-uri's was that my background images rendered as soon as the stylesheet was downloaded, as opposed to the gradual loading we see otherwise

It's nice that we have this technique available, but I won't be using it too much in the future. I do recommend trying it out though, just so you know for yourself

Solution 5:

I'd more inclined to use CSS Sprites to combine the images and save on requests. I've never tried the base64 technique but it apparently doesn't work in IE6 and IE7. Also means that if any images changes then you have to redeliver the whole lost, unless you have multiple CSS files, of course.