Is embedding background image data into CSS as Base64 good or bad practice?

175,971

Solution 1

It's not a good idea when you want your images and style information to be cached separately. Also if you encode a large image or a significant number of images in to your css file it will take the browser longer to download the file leaving your site without any of the style information until the download completes. For small images that you don't intend on changing often if ever it is a fine solution.

as far as generating the base64 encoding:

Solution 2

This answer is out of date and shouldn't be used.

1) Average latency is much faster on mobile in 2017. https://opensignal.com/reports/2016/02/usa/state-of-the-mobile-network

2) HTTP2 multiplexes https://http2.github.io/faq/#why-is-http2-multiplexed

"Data URIs" should definitely be considered for mobile sites. HTTP access over cellular networks comes with higher latency per request/response. So there are some use cases where jamming your images as data into CSS or HTML templates could be beneficial on mobile web apps. You should measure usage on a case-by-case basis -- I'm not advocating that data URIs should be used everywhere in a mobile web app.

Note that mobile browsers have limitations on total size of files that can be cached. Limits for iOS 3.2 were pretty low (25K per file), but are getting larger (100K) for newer versions of Mobile Safari. So be sure to keep an eye on your total file size when including data URIs.

http://www.yuiblog.com/blog/2010/06/28/mobile-browser-cache-limits/

Solution 3

If you reference that image just once, I don’t see a problem to embed it into your CSS file. But once you use more than one image or need to reference it multiple times in your CSS, you might consider using a single image map instead you can then crop your single images from (see CSS Sprites).

Solution 4

One of the things I would suggest is to have two separate stylesheets: One with your regular style definitions and another one that contains your images in base64 encoding.

You have to include the base stylesheet before the image stylesheet of course.

This way you will assure that you're regular stylesheet is downloaded and applied as soon as possible to the document, yet at the same time you profit from reduced http-requests and other benefits data-uris give you.

Solution 5

Base64 adds about 10% to the image size after GZipped but that outweighs the benefits when it comes to mobile. Since there is a overall trend with responsive web design, it is highly recommended.

W3C also recommends this approach for mobile and if you use asset pipeline in rails, this is a default feature when compressing your css

http://www.w3.org/TR/mwabp/#bp-conserve-css-images

Share:
175,971
Dimitar Christoff
Author by

Dimitar Christoff

Javascript is to java what hamster is to ham. Follow me on Github

Updated on July 26, 2020

Comments

  • Dimitar Christoff
    Dimitar Christoff almost 4 years

    I was looking at the source of a greasemonkey userscript and noticed the following in their css:

    .even { background: #fff url(data:image/gif;base64,R0lGODlhBgASALMAAOfn5+rq6uvr6+zs7O7u7vHx8fPz8/b29vj4+P39/f///wAAAAAAAAAAAAAAAAAAACwAAAAABgASAAAIMAAVCBxIsKDBgwgTDkzAsKGAhxARSJx4oKJFAxgzFtjIkYDHjwNCigxAsiSAkygDAgA7) repeat-x bottom}
    

    I can appreciate that a greasemonkey script would want to bundle anything it can within the source as opposed to host it on a server, that's obvious enough. But since I had not seen this technique previously, I considered its use and it seems appealing for a number of reasons:

    1. It will reduce the amount of HTTP requests on page load, thus enhancing performance
    2. If no CDN, then it will reduce the amount of traffic generated through cookies being sent alongside of images
    3. CSS files can be cached
    4. CSS files can be GZIPPED

    Considering that IE6 (for instance) has problems with cache for background images, this seems like it's not the worst idea...

    So, is this a good or bad practice, why WOULDN'T you use it and what tools would you use to base64 encode the images?

    update - results of testing

    Nice, but it will be slightly less useful for smaller images, I guess.

    UPDATE: Bryan McQuade, a software engineer at Google, working on PageSpeed, expressed at ChromeDevSummit 2013 that data:uris in CSS is considered a render-blocking anti-pattern for delivering critical/minimal CSS during his talk #perfmatters: Instant mobile web apps. See http://developer.chrome.com/devsummit/sessions and keep that in mind - actual slide

  • Duncan Beevers
    Duncan Beevers over 13 years
    It just means that you should have one css class on an element for referencing the background image, and another css class for referencing the offsets into that image to use for that element.
  • Dimitar Christoff
    Dimitar Christoff over 12 years
    good point re mobile/responsive though I am not sure of the 10%, where do you get that data from?
  • Rafael Sanches
    Rafael Sanches about 12 years
    This is correct. The slowest thing in any mobile device is the open/close of http connections. Minimizing them is recommended.
  • Fabrizio Calderan
    Fabrizio Calderan over 11 years
    despite w3 results, in some test I did the size of images increased by ~25% :(
  • Adam Tolley
    Adam Tolley over 11 years
    you should have NO classes on the elements that describe how material is presented - those classes should be well-named and semantic (this is not always possible, but good to shoot for) If multiple elements use the same image, and you would like to encode that image in the CSS, just leave the image out of the declarations, and use a later css rule to declare and embed the image for multiple selectors/classes.
  • Léon Pelletier
    Léon Pelletier over 11 years
    I guess it can raise up to 33% if it's just impossible to zip it.
  • Leo
    Leo about 11 years
    If you're shooting for semantic classes and also want the image data just once, you can have a separate style which lists all the relevant selectors, and then offsets defined in per-selector styles. Of course, for a very small image in a lot of places, the selector list might be bigger than the data...
  • Rafael Sanches
    Rafael Sanches almost 11 years
    on mobile 10% is nothing compared to the creation of http connections
  • Luke Page
    Luke Page almost 11 years
    less had a data-uri function that will inline a image lesscss.org/#reference
  • Rob
    Rob about 10 years
    I like this in theory. Can anyone think of any arguments against?
  • vsync
    vsync almost 10 years
    it is a good idea if you want to have minimum protection for those images so they wouldn't* be cached or could be downloaded by right-clicking -> save
  • magritte
    magritte over 9 years
    "It's not a good idea when you want your images and style information to be cached separately" - there's nothing to stop you having all the images in a seperate .css file.
  • Adam Katz
    Adam Katz over 8 years
    Without compression, base64 should consume 25% extra space, though I had a test PNG 523b → base64 710b (35.8%, wtf) → gz 560b (7.5%). Compression will always lower that since base64 only uses a small number of characters. Also consider HTTP header sizes. Try using pngquant to further compress your base image if you care about every byte.
  • Chinoto Vokro
    Chinoto Vokro over 7 years
    In order to avoid multiple classes and only specify a sprite sheet once, you could use an attribute selector: [emoji] {background-image: url(data:image/png;base64,qwedfcsfrtgyu/=);} [emoji=happy] {background-position: -20px 0px;}
  • TomeeNS
    TomeeNS almost 7 years
    My practice and tests does not confirm your statement. Sorry.
  • Craig
    Craig about 6 years
    I was just Googling this myself to find out if it is a good idea and came here. In my case the images are all just UI stuff and I was thinking this would be a good idea. Not sure if it's better than using css sprites but I feel it is easier to manage if you do make changes in the future. Would love to know if anyone has anything against this?