Automatic data URI embedding in CSS files
Last week, I posted about data URIs and why they’re an interesting feature of web browsers. In the conclusion, I mentioned that the best use of data URIs is to embed them in CSS files so that they have the best chance of being cached by the browser. I got a lot of responses, both on this blog and via other means that people were very excited about data URIs and were ready to make the leap to using them in CSS. This left me with me believing that an interesting time is upon us.
The problem
Even though Internet Explorer prior to version 8 doesn’t support data URIs, the majority of people seem willing to serve alternate content to those less-capable browsers and serve the more optimal content to those that can handle it. The problem is that millions of web sites are currently using CSS files that reference image files in the traditional manner, and all of those would have to be converted over to use data URIs. No one wants to maintain multiple versions of CSS files, so it would be best if this conversion process could be automatic.
Introducing CSSEmbed
I spent the past couple of days coding and am proud to introduce CSSEmbed, a tool to automatically embed images into CSS files as data URIs. This is a very small, simple tool that reads in a CSS file, identifies the images referenced within, converts them to data URIs, and outputs the resulting style sheet. The newly-created stylesheet is an exact duplicate of the original, complete with comments and indentation intact; the only difference is that all references to image files have been replaced with data URIs. Because it preserves the original formatting of the style sheet, it can be used both on nicely-formatted source code and crunched source code without worry.
CSSEmbed is written in Java and requires Java 1.5+ to run. To get started, download the JAR file. All of the dependencies are included in that JAR file, so there is no need to mess around with setting up classpaths or downloading other dependencies. Basic usage is as follows:
java -jar cssembed-x.y.z.jar -o <output filename> <input filename>
For example:
java -jar cssembed-x.y.z.jar -o styles_new.css styles.css
When the -o flag is omitted, the output ends up on stdout, thus you can direct the output to a file directly:
java -jar cssembed-x.y.z.jar styles.css > styles_new.css
Complete usage instructions are available using the -h flag:
Usage: java -jar cssembed-x.y.z.jar [options] [input file] Global Options -h, --help Displays this information. --charset Character set of the input file.-v, --verbose Display informational messages and warnings.-root Prepends to all relative URLs. -o Place the output into . Defaults to stdout.
CSSEmbed is smart in the way it identifies images. If the image location begins with “http://”, then the tool automatically downloads the file and converts it to a data URI. If the image location is a relative path (i.e., contains “../”), CSSEmbed looks for the file locally in relation to the style sheet file’s location. If the files is an absolute path without “http://” specified, such as “/images/image.png”, you’ll need to provide a root via the --root option. When specified, the root gets prepended to all image locations that don’t already begin with “http://”.
For more information about CSSEmbed, please check out the documentation. You can also download the source (MIT License) from the GitHub project. CSSEmbed is in its very early stages, so feedback is welcome. If you find any bugs, please use the issue tracker to report them.
…and introducing DataURI
When I was researching data URIs, I didn’t come across any simple data URIs generators. There’s Hixie’s data URI kitchen, but that’s just available online. What I really wanted was something to be run on the command line so that I could create CSSEmbed. As such, I created DataURI, which is a simple tool that reads in a file and outputs the data URI representation. DataURI is the underlying engine that CSSEmbed uses to create its data URIs.
DataURI is also written in Java and requires Java 1.5+ to run. As with CSSEmbed, there is a single JAR file containing all of the dependencies. The same general command line options are available, so the basic usage is very similar to CSSEmbed:
java -jar datauri-x.y.z.jar -o <output filename> <input filename>
For example:
java -jar datauri-x.y.z.jar -o output.txt image.png
The files to encode don’t have to be local, you can include a URL on the command line and it will download and encode them:
java -jar datauri-x.y.z.jar -o output.txt http://www.your.domain.com/image.png
When the -o flag is omitted, the output ends up on stdout, thus you can direct the output to a file directly:
java -jar datauri-x.y.z.jar styles.css > styles_new.css
Complete usage instructions are available using the -h flag:
Usage: java -jar datauri-x.y.z.jar [options] [input file]Global Options -h, --help Displays this information. --charset <charset> Character set of the input file. -v, --verbose Display informational messages and warnings. -m, --mime <type> Mime type to encode into the data URI. -o <file> Place the output into <file>. Defaults to stdout.
DataURI is capable of creating data URIs for images and some text files (for the complete list, please see the documentation). The source code is available (MIT License) from the GitHub project and you can report issues there as well.
Acknowledgements
I was inspired to create these tools after reading, Not Just a Pretty Face: Performance and the New Yahoo! Search, by Ryan Grove, Stoyan Stefanov, and Venkateswaran Udayasankar from the Yahoo! Search team. The section about data URIs led me to do more research and ultimately to the creation of both CSSEmbed and DataURI.
I’m nowhere near as good at Java as I am with JavaScript, and so having a great working example made this development easier. To that end, I must thank Julien Lecomte as I used the source code for YUI Compressor as a guideline for how to organize my code. Julien’s code is so clean that it was easy to setup my projects in the same manner. I also used his Ant file as a basis for my own.
Followup
Data URIs are definitely exciting as a means of improving web site performance. Every big push forward in development technique needs a good set of tools to increase adoption. I sincerely hope that CSSEmbed and DataURI can help people get started in the creation and usage of data URIs.
Update (27-June-2010): Updated links to DataURI source on GitHub (now part of CSSEmbed repository).
Disclaimer: Any viewpoints and opinions expressed in this article are those of Nicholas C. Zakas and do not, in any way, reflect those of my employer, my colleagues, Wrox Publishing, O'Reilly Publishing, or anyone else. I speak only for myself, not for them.
Both comments and pings are currently closed.




24 Comments
This is a nice. I was actually looking for a datauri generator. Will try this for sure.
JP on November 3rd, 2009 at 4:24 pm
Is there an easy way to create a fallback for when data uris are not supported? I know there is a JS solution. That just injects a small datauri in your page, but I wonder if there is a better way to do it.
V1 on November 6th, 2009 at 5:31 pm
Any places to report bugs?
V1:build V1$ java -jar cssembed-0.1.2.jar -o datauri.css cssbefore.css
Exception in thread “main” java.lang.UnsupportedClassVersionError: Bad version number in .class file
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:675)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:260)
at java.net.URLClassLoader.access$100(URLClassLoader.java:56)
at java.net.URLClassLoader$1.run(URLClassLoader.java:195)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:316)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:280)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:374)
V1:build V1$ java -version
java version “1.5.0_20″
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_20-b02-315)
Java HotSpot(TM) Client VM (build 1.5.0_20-141, mixed mode, sharing)
Mac OSX 1.5.8, terminal. Full version downloaded.
V1 on November 6th, 2009 at 5:39 pm
I’ve downloaded 0.1.2 from Github, however trying it out on some of my CSS files it outputs them untouched. The stylesheets are uses relative paths (“../images/someimage.png”), I’m on an Ubuntu 8.10.
Ceriak on November 6th, 2009 at 6:03 pm
@V1 – That’s an entirely separate topic that a lot of people have covered online already. Please see Stoyan and Hedger’s links. For your problem, try updating your JRE/JDK. I’ve had a few people say that they’ve had trouble, and updating has helped.
For everyone, please report issues at the addresses mentioned in the blog post:
DataURI: http://github.com/nzakas/datauri/issues
CSSEmbed: http://github.com/nzakas/cssembed/issues
Nicholas C. Zakas on November 7th, 2009 at 1:11 am
[...] creating these tools to ease the burden for web developers. Read Nicholas’ original blog post Automatic data URI embedding in CSS files for examples and more [...]
High Performance Web Sites :: CSSEmbed - automatically data: URI-ize on November 16th, 2009 at 2:52 pm
[...] 下载:http://github.com/nzakas/cssembed/downloads/ 文档:http://www.nczonline.net/blog/2009/11/03/automatic-data-uri-embedding-in-css-files/ 快速上手: java -jar cssembed-x.y.z.jar -o styles_new.css [...]
好用的命令行工具 « Kejun’s Blog on November 17th, 2009 at 6:03 am
- It would be real nice if you added a *background for IE7 and lower like so:
background: url(data:image/png;base64,GOUEYFGKWGF=) no-repeat 0 0;
*background: url(imgs/foo.png) no-repeat 0 0;
- I’d love the option of only doing this for images smaller than X kB in size.
- It’s to give a warning when a certain image is referenced more than once in the CSS, to avoid having the same datablock twice.
Jaap on November 17th, 2009 at 12:44 pm
@Jaap – Please log any requests at http://github.com/nzakas/cssembed/issues
Nicholas C. Zakas on November 17th, 2009 at 11:41 pm
Convert CSS images to data URIs automatically with CSSEmbed…
I wanted to play around with Nicholas Zakas’ new tool for automatically converting CSS background images to data URIs so I tested it out with the CSS on this site. CSSEmbed accepts a CSS file and outputs a copy with all image references replac…
ravelrumba on November 23rd, 2009 at 1:21 am
this is great! thank you!
Nagaraj Hubli on November 27th, 2009 at 9:15 am
[...] And here’s a great tool from Nicholas C. Zakas – CSSEmbed – it reads the CSS file you want, finds all the images references, converts images to dataURIes [...]
data URI browser issues « Sharovatov’s Weblog on November 29th, 2009 at 4:30 am
I see that data URI’s is not working in IE8.. is it supposed to be working in IE8?
Nagaraj Hubli on November 30th, 2009 at 6:04 am
[...] too long ago, I wrote about data URIs and released a couple of tools to help generate them. A key part of the data URI equation is base64 encoding. Base64 encoding is [...]
Computer science in JavaScript: Base64 encoding | NCZOnline on December 8th, 2009 at 9:01 am
Really really wonderful tool Nicholas, appreciate your efforts… Thanks for sharing.
Deepu Balan on December 24th, 2009 at 3:06 am
@V1 – OS X tends to lag in version numbers (I think the Mac JRE is at 1.5, whereas the current is 1.6). That’s the error you’re getting.
Great idea, though – I was just looking for something like this that runs on my computer (not the wonderful cloud).
mathgeek618 on January 4th, 2010 at 6:17 pm
[...] This creates a new file named myStylesheet-base64.css where all image references have become base64-encoded. Awesome, right? It also supports conversion for MHTML for targeting older versions of Internet Explorer. Nicolas has written more about it and how it works in Automatic data URI embedding in CSS files. [...]
How to reduce the number of HTTP requests - Robert's talk on January 14th, 2010 at 7:55 pm
hi Nicolas,
I ran a css file through CSSembed and the image encoding seems to go wrong:
background:url(data:text/html;charset=UTF-8;base64,) 0 0 no-repeat;
This is for all images in the css.
My command was:
java -jar cssembed-0.3.2.jar –root http://www.snsbank.nl/static/snsbank -o gx-overrule_beautified_datauri.css gx-overrule_beautified.css
I’m on Windows Vista. Java version 1.6.0_17.
I’d appreciate your feedback!
txs,
Aaron
Aaron Peters on January 19th, 2010 at 5:16 pm
remove that last comment (and this one)…
my command was bad, with the root specified and the css file having relative paths to the images, like this: url(../path/to/file.gif
What I find strange is that CSSembed doesn’t abort if it can’t download any images, and thus can’t do any base64 encoding.
I guess that’s one for http://github.com/nzakas/cssembed/issues …
Aaron Peters on January 19th, 2010 at 5:55 pm
I wrote a ruby rack plugin which does exactly this. Take a look at http://github.com/minad/rack-embed
Daniel on January 22nd, 2010 at 8:02 pm
Hi,
indeed CSS is a great tool, it does exactly what the web community was missing. However I’d like to add that absolute paths make the program crash. Once the background is absolute to the document root as background:url(/images/….sprite.png); it says no file exists in …../styles/images/sprite.png … but the case is that the image is relatively on the same level as the styles folder. Whatever with simple mass replace everything’s working fine!
Thanks!
stoimen on March 2nd, 2010 at 11:33 am
@Stoimen – Please report any issues at http://github.com/nzakas/cssembed/issues
Nicholas C. Zakas on March 3rd, 2010 at 12:21 am
[...] the moment of writing). For a tool to automate the dataURI-zation/MHTML-ization, be sure to check Nicholas Zakas‘ [...]
Performance Calendar » Blog Archive » Data URIs, MHTML and IE7/Win7/Vista blues on November 30th, 2010 at 3:48 pm
[...] here, you should be able to include targets for things like DataURIs using a command line tool like CSSEmbed and optimization to your jpeg files using a tool like JPEGtran. You can find the completed build [...]
Performance Calendar » An Introduction to Automating Performance with Phing on December 5th, 2010 at 5:51 am
Comments are automatically closed after 14 days.