3 mins

Base64-encoding images for use in web pages has been around for a while. Conventional wisdom stated that images should be encoded as base64 text for inline use in html for two primary reasons:

  • reduce the number of http requests in a single page
  • improve the performance of the page by reducing page load time

There’s no disputing - at all - that inlining the encoding of an image in the img tag eliminates the additional page load of a real image. What is disputed, at least somewhat recently, is the second claim about performance improvements.

It is common to read strongly-worded opinions advising against use of base64 encoding, as it “…increases the overall payload size” of a page in which it is used. That is, the base64 textual encoding of an image is said to be larger than the original, thus increasing page load time because more bits are moving across the wire & into the browser’s window object.

This is only partly true.

For small images, base64 will always produce a smaller page footprint. And for really large images - referring to file size here - base64 will also produce a smaller footprint by at least an order of magnitude.

An image with a 2.4Mb original size can be repeatedly base64-encoded to 151Kb. I’m using my resource handler API to do that, which is a single request and pushes 202Kb into the window. Returning the encoded image - all text - into the window uses the 151Kb. Caching the page reduces subsequent loads by almost 50Kb.

Aggressive optimization of the workers further reduces the API page load by another 70Kb, putting this solidly in the sub-100Kb range. That’s an acceptable window size that loads into the page in just over 500 milliseconds. The image itself doesn’t have a load-time, per se, (at 4 microseconds, do you really care?) and is generated in approximately 1 millisecond.

This means that in the minimal case, I have at least two requests to produce a single image. Adding another image into the page does not add another API call, at least in the trivial case, so this cost is generally borne just once per [n] images. It is fast & efficient.

Those in-between images are the ones that will produce base64 text strings that are larger, byte-wise, than the original image that’s encoded in them. This is counter-intuitive and has a lot of variables, but my testing supports this with solid data.

Finding the boundaries between small and large requires more modeling, but it certainly looks like if you test for file size prior to encoding, the image can be rendered using the method that’s best based upon size.

- jbminn