John Dyer

Technology and web development in curly bracket languages {Javascript, C#, ActionScript}

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

by John Dyer 26. January 2010 18:42

 

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

Comments

1/26/2010 8:46:22 PM # Chris Korhonen Chris Korhonen United States | Reply
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.
1/26/2010 9:23:09 PM # LeRoy LeRoy United States | Reply
Thanks a bunch for making this tool available! I hadn't considered this form of optimization until now.
1/26/2010 9:45:30 PM # Sean Patterson Sean Patterson United States | Reply
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 ::]
1/27/2010 6:26:52 PM # John Dyer John Dyer United States | Reply
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.
John Dyer's last post: feedproxy.google.com/.../post.aspx" rel="nofollow">Simple Cross-Browser HTML5 video with a single H.264 file and fallback options
1/26/2010 10:36:46 PM # Michael Lang Michael Lang United States | Reply
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 1x1 transparent section on the sprite.  Use the 1x1 transparent image at the bottom of your page that is visible at load time...  That then preloads the entire sprite.
1/27/2010 6:29:42 PM # John Dyer John Dyer United States | Reply
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.
John Dyer's last post: feedproxy.google.com/.../post.aspx" rel="nofollow">Simple Cross-Browser HTML5 video with a single H.264 file and fallback options
1/27/2010 8:41:34 PM # Sean Patterson Sean Patterson United States | Reply
[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
1/29/2010 8:54:53 PM # slipy slipy Slovakia | Reply
Isn't better to use "normal" CSS everytime? With base64 is too many problems.

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading



Web Statistics