Optimizing CSS with Base64 Embedded Images (with Bonus Utility!)

 

As I design a new site (current site | early demo of new site), I am working through what combination of technologies (CDN, sprites, caching, gzipping, etc.) we want to use to optimize it. One tool I’m looking at is embedding images in CSS with base64 strings. Instead of the browser needing to make several calls, one for the CSS file and then one for each image, base64 embedding means that all of the images are embedded within the CSS file itself.

It’s great for small images or images that only show up on :hover or mouseover and you don’t want there to be any delay in the image appearing. Here’s what it looks like:

Normal CSS

.myclass {
width: 45px;
background: transparent url(myimage.jpg) top left no-repeat;
}

CSS with Base64 Embedded Image

.myclass {
width: 45px;
background: transparent url(data:image/png;base64,LONG-STRING-OF-BASE64-TEXT) top left no-repeat;
}

Problems with Base64

  1. Works in all browsers except IE6 and IE7. Solution: use a conditional comments to give IE6/7 a stylesheet that still references the images.
  2. Base64 is bigger than real images: In my tests a base64 encoded string image is somewhere around 150% the size of a regular image. This means it’s unusable for large images.
  3. Hard to manage: If you change the image, you’ll need to reembed the base64 string. You also have to maitain a separate IE stylesheet.

How to manage it

To help figure out which images were worth embedded and help

manage it, I developed a small utility that analyzes a CSS file and allows you to select which images you want to embed. You can also preselect them by adding a comment somewhere within your CSS declaration that says /*embed*/

What It Does

  • Finds all image URLs in your CSS file (note: no CSS3 multiples or borders)
  • Shows the size difference between the image and the base64 string
  • Shows the final size output size and the GZipped size for comparison to the original
  • Removes comments and whitespace if you want
  • Creates a new base64 stylesheet and a IE6/7 stylesheet with references to the original image

Download

11 thoughts on “Optimizing CSS with Base64 Embedded Images (with Bonus Utility!)

  1. Another tip – if you are using Ruby on Rails, take a look at the Jammit gem. It handles asset packaging at deploy time and can automatically convert images in a specific directory into base64 embedded images within your CSS (and MHTML files for IE6/7).
    Very impressive and totally transparent to your workflow.

  2. Hey John,
    I like the tool and the technology seems really interesting! To play "provocateur" a little, what additional benefits to the CSS images do you see outside of the first time page load? It seems to me that having the larger file size and maintenance issues of a massive text blob would be a major concern. Doesn’t the browser already cache the images used after the first load? In addition, specifying a subdomain for your images (img.dts.edu) would increase the performance and make it easy to change layouts on the fly.
    Looking forward to your thoughts
    [:: Sean ::]

  3. An alternative would be to make an image sprite with all your images in it. The first location that needs an image will load the entire sprite. The other images shown on hover will already be downloaded and will appear instantly.
    If no images are used until hover, then include a 1×1 transparent section on the sprite. Use the 1×1 transparent image at the bottom of your page that is visible at load time… That then preloads the entire sprite.

  4. One of the biggest concerns today in web design is the user’s experience the first time they hit a page. Subsequent caching is great, but you want that first experience to be solid. The number of different things the browser has to load plays a part in that experience.
    On the design I’m working on, we have a dropdown menu that uses background images. Those background images don’t normally load until a user mouses over the menu item. I would rather that the CSS file is a few KB bigger than have the user experience a delay downloading the images for each menu. There are other ways to accomplish this, so I build this tool to help decide if base64 is a good way to go for your current project.

  5. Yes, sprites are another good way to help manage images.
    Of course sprites also trade-offs. For example, it’s a lot of work to manage a giant image with lots of little images inside and keep track of the background positions of each image. In addition, loading the same giant sprite into a browsers memory several times can cause browser memory usage to rise. I love sprites for certain things, but neither it nor base64 are one-size-fits-all solutions.

  6. [quuote]I love sprites for certain things, but neither it nor base64 are one-size-fits-all solutions.[/quote]
    Precisely! So how is the base64 layout working for you currently? The demo site loads visibly faster than the original, and I’m thinking this could be really cool

  7. the problem is that your CSS is bigger and has to be reloaded if you change anything in it. i know, we are talking about first page load and some other technics like CSS sprites have the same type of issues.
    anyway, this can be a problem in some cases and must be considered.
    P.S. : I came here for the jPicker which is excellent, thanks a lot for your great work.
    P.P.S. : I’m using a Mac. so an AIR version would have be better for me – and for the Linux folks. You wouldn’t do a website that’s only visible to Windows people so why not try to keep this philosophy when developing desktop softwares ? 😉 Anyway this tool looks very cool too.

Comments are closed.