484

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

Dimitar Christoff
  • 26,147
  • 8
  • 50
  • 69
  • Do some test runs? Would be interesting how much the compression can compensate the fact you base64 encode it. – Dykam Jul 14 '09 at 08:39
  • posted the results of the test, also avail on my blog http://fragged.org/compressing-jpeg-images-via-base64-data-and-gzip-deflating_1264.html – Dimitar Christoff Feb 18 '11 at 15:35
  • 5
    Good Question. Just wanted to add that it doesnt work for IE7 and below. But there is some work arounds. Here is a nice article about it http://jonraasch.com/blog/css-data-uris-in-all-browsers – MartinF Jun 29 '11 at 14:46
  • Doesn't work on my IE8 either... – tsadiq Jan 03 '12 at 10:25
  • 2
    Adding more `PRO:` cache limits on cellular devices... `CON:` some images should be treated as content rather than simple presentation and thus are better fit for HTML IMG tags than CSS background images. – one.beat.consumer Apr 09 '12 at 17:44
  • 1
    @DimitarChristoff: I've been a fan of embedding small icons with base64 because of its relative ease (when comparing with aggressive spriting) and was happy to accept the size overhead. Thanks for pointing out that it's not always the case (i.e. gzipped base64 embed may be better in terms of absolute asset size as well) – Oleg Nov 10 '12 at 01:54
  • Gzipped base-64 will almost always be worse than just gzipping the original in the first place. It's completely false to suggest that you can only send compressed resources that are text in nature. Most people don't bother with gzipping anything non-text, as there often isn't a huge benefit for images that already have built-in compression, such as PNG. – Brad Dec 23 '12 at 05:19
  • **Wrong !** *`base64`* encode 8bit bytes / 6bit bytes. So to growing is significantly **more** than 10%! Resulting size `r` = **133%** Original size `o`: `r=8/6*o -> r=4/3*o -> r=133.333/100*o` – F. Hauri - Give Up GitHub Feb 20 '13 at 07:52
  • One disadvantage is that chrome on android renders svgs as bitmaps when used in as a css background-image. More details on the chromium issue tracker: https://code.google.com/p/chromium/issues/detail?id=161982 – matt_50 Mar 04 '13 at 10:38

12 Answers12

169

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:

zx485
  • 28,498
  • 28
  • 50
  • 59
poop a birck
  • 2,057
  • 1
  • 14
  • 4
  • less had a data-uri function that will inline a image http://www.lesscss.org/#reference – Luke Page Jul 26 '13 at 12:19
  • 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 – vsync Jun 09 '14 at 14:59
  • "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. – magritte Sep 24 '14 at 12:46
  • My practice and tests does not confirm your statement. Sorry. – TomeeNS May 26 '17 at 15:49
57

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/

whitneyland
  • 10,632
  • 9
  • 60
  • 68
Mike Brittain
  • 805
  • 7
  • 4
24

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).

Gumbo
  • 643,351
  • 109
  • 780
  • 844
  • 16
    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. – Duncan Beevers Oct 01 '10 at 19:22
  • 4
    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. – Adam Tolley Oct 28 '12 at 23:08
  • 1
    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... – Leo Apr 25 '13 at 12:09
  • 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;}` – Chinoto Vokro Dec 17 '16 at 09:25
22

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.

ximi
  • 596
  • 5
  • 17
  • 1
    I like this in theory. Can anyone think of any arguments against? – Rob Mar 31 '14 at 22:02
  • 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? – Craig Mar 20 '18 at 23:26
21

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

Greg
  • 4,509
  • 2
  • 29
  • 22
  • good point re mobile/responsive though I am not sure of the 10%, where do you get that data from? – Dimitar Christoff Jan 16 '12 at 09:51
  • 3
    This is correct. The slowest thing in any mobile device is the open/close of http connections. Minimizing them is recommended. – Rafael Sanches Feb 16 '12 at 19:03
  • despite w3 results, in some test I did the size of images increased by ~25% :( – Fabrizio Calderan Sep 28 '12 at 13:13
  • 2
    I guess it can raise up to 33% if it's just impossible to zip it. – Léon Pelletier Dec 08 '12 at 09:29
  • 1
    on mobile 10% is nothing compared to the creation of http connections – Rafael Sanches Jul 10 '13 at 19:36
  • *Without* compression, [base64 should consume 25% extra space](https://en.wikipedia.org/wiki/Binary-to-text_encoding#Encoding_standards), 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](https://pngquant.org/) to further compress your base image if you care about every byte. – Adam Katz Sep 25 '15 at 22:15
5

I disagree with the recommendation to create separate CSS files for non-editorial images.

Assuming the images are for UI purposes, it's presentation layer styling, and as mentioned above, if you're doing mobile UI's its definitely a good idea to keep all styling in a single file so it can be cached once.

tim
  • 433
  • 1
  • 6
  • 8
3

I tried to create an online concept of CSS/HTML analyzer tool:

http://www.motobit.com/util/base64/css-images-to-base64.asp

It can:

  • Download and parse HTML/CSS files, extract href/src/url elements
  • Detect compression (gzip) and size data on the URL
  • Compare original data size, base64 data size and gzipped base64 data size
  • Convert the URL (image, font, css, ...) to a base64 data URI scheme.
  • Count number of requests which can be spared by Data URIs

Comments/suggestions are welcome.

Antonin

Antonin Foller
  • 101
  • 1
  • 1
3

You can encode it in PHP :)

<img src="data:image/gif;base64,<?php echo base64_encode(file_get_contents("feed-icon.gif")); ?>">

Or display in our dynamic CSS.php file:

background: url("data:image/gif;base64,<?php echo base64_encode(file_get_contents("feed-icon.gif")); ?>");

1 That’s sort of a “quick-n-dirty” technique but it works. Here is another encoding method using fopen() instead of file_get_contents():

<?php // convert image to dataURL
$img_source = "feed-icon.gif"; // image path/name
$img_binary = fread(fopen($img_source, "r"), filesize($img_source));
$img_string = base64_encode($img_binary);
?>

Source

ucefkh
  • 2,509
  • 2
  • 22
  • 18
3

In my case it allows me to apply a CSS stylesheet without worrying about copying associated images, since they're already embedded inside.

Rolf
  • 5,550
  • 5
  • 41
  • 61
2

Bringing a bit for users of Sublime Text 2, there is a plugin that gives the base64 code we load the images in the ST.

Called Image2base64: https://github.com/tm-minty/sublime-text-2-image2base64

PS: Never save this file generated by the plugin because it would overwrite the file and would destroy.

0

Thanks for the information here. I am finding this embedding useful and particularly for mobile especially with the embedded images' css file being cached.

To help make life easier, as my file editor(s) do not natively handle this, I made a couple of simple scripts for laptop/desktop editing work, share here in case they are any use to any one else. I have stuck with php as it is handling these things directly and very well.

Under Windows 8.1 say---

C:\Users\`your user name`\AppData\Roaming\Microsoft\Windows\SendTo

... there as an Administrator you can establish a shortcut to a batch file in your path. That batch file will call a php (cli) script.

You can then right click an image in file explorer, and SendTo the batchfile.

Ok Admiinstartor request, and wait for the black command shell windows to close.

Then just simply paste the result from clipboard in your into your text editor...

<img src="|">

or

 `background-image : url("|")` 

Following should be adaptable for other OS.

Batch file...

rem @echo 0ff
rem Puts 64 encoded version of a file on clipboard
php c:\utils\php\make64Encode.php %1

And with php.exe in your path, that calls a php (cli) script...

<?php 

function putClipboard($text){
 // Windows 8.1 workaround ...

  file_put_contents("output.txt", $text);

  exec("  clip < output.txt");

}


// somewhat based on http://perishablepress.com/php-encode-decode-data-urls/
// convert image to dataURL

$img_source = $argv[1]; // image path/name
$img_binary = fread(fopen($img_source, "r"), filesize($img_source));
$img_string = base64_encode($img_binary);

$finfo = finfo_open(FILEINFO_MIME_TYPE); 
$dataType = finfo_file($finfo, $img_source); 


$build = "data:" . $dataType . ";base64," . $img_string; 

putClipboard(trim($build));

?>
PaulANormanNZ
  • 191
  • 1
  • 7
0

As far as I have researched,

Use : 1. When you are using an svg sprite. 2. When your images are of a lesser size (max 200mb).

Don't Use : 1. When you are bigger images. 2. Icons as svg's. As they are already good and gzipped after compression.