If you are considering using data-uris instead of CSS sprites for your background images, you are probably doing this (at least partly) for performance reasons. Each image you can stuff into a data-uri saves you an HTTP call, after all.
But if you are thinking about performance, you will also be paying attention to the size of your CSS, and you might be concerned about the use of the same background image multiple times, but in different contexts. With image files, referencing the same background image multiple times is lightweight, but with data-uris, the base-64 encoded data takes up a lot more space:
.monkey {
background-image:url(http://sunpig.com/martin/code/2011/gzipcss/erlenmeyer.png);
}
.fez {
background-image:url(http://sunpig.com/martin/code/2011/gzipcss/erlenmeyer.png);
}
vs.
.monkey {
background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAlotsmoredata...");
}
.fez {
background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAlotsmoredata...");
}
There are, of course, other ways of assigning the same background image to different elements (you can group your selectors, or create a mixin classname for use in your HTML). But if, for whatever reason, you do end up embedding the same base-64-encoded resource multiple times in the same file, provided you are serving your CSS gzipped, you don't need to worry too much about the extra file size.
The reason for this is that the DEFLATE algorithm (which powers gzip compression) is all about eliminating duplicate strings. When the algorithm finds the second instance of a long base-64-encoded string, it can just replace it with a reference to the first instance. And because the reference is much shorter than the base-64 block itself, the size increase of the gzipped file is negligible.
Here's a short table showing some actual figures. The files 1.css, 2.css, and 3.css contain 1, 2, and 3 copies of the same base-64-encoded image respectively. I used nginx (0.7.67) on my laptop to check the gzipped file sizes.
| File | Uncompressed size (bytes) | Gzipped size (bytes) |
|---|---|---|
| 1.css | 1437 | 1139 |
| 2.css | 2871 | 1135 |
| 3.css | 4311 | 1156 |
Note that the file with the data embedded twice comes out even smaller than the version with only one copy. gzip can be a bit strange that way, which is why you should always check the gzipped version of any CSS or JS files you're fine-tuning for size. Minor optimizations don't always work out the way you might expect.
Just for clarity: embedding the same resource multiple times is not always a great strategy for re-usable CSS. But when you do it, at least you don't have to worry about file size bloat.


unwesen
A few comments, seeing that I wrote a performance testing tool for websites not so long ago :)
Put the above together, and you're likely to trade in some small latency on the first request of an image file for potentially substantial bandwidth increases (which in turn affect latency again even in an ideal world, but more so when you're using a web server that doesn't deal well with multiple persistent connections); the specifics depend largely on how often your CSS changes relative to your images.
More specifically, the latency improvement you're gaining is all about how fast the browser parses & applies CSS: with an in-line image, it can render the image the moment the CSS is applied.
The upshot? I'd probably try serving your images from a separate webserver, possibly powered by node.js or a similar lightweight server implementation that is great at handling tons of connections. It'll help with scalability (quite a bit) while hurting latency only on the very first request of an image in comparison with embedding images in CSS.
None of which suggests that what Martin wrote is wrong. Absolutely not. I just wouldn't recommend embedding images in CSS in all but the most extreme cases. As always, though, it's only testing that can tell you wether it's a good idea or not...