How to reduce the number of HTTP requests

As you might be aware of, I believe web site performance is truly a critical success factor, and I have written about it before in How to improve your web site performance – tips & tricks to get a good YSlow rating

What we have

With the advent of such great tools such as YSlow and Page Speed, looking at the practices of web sites like Google and Yahoo! and reading the excellent performance work done by Steve Souders, we have really learnt a lot, and have great resources.

Reducing the number of HTTP requests

One of the crucial things when it comes to improving performance is reducing the number of HTTP requests. According to Steve Souders: “An extra HTTP request adds 200+ milliseconds to a page (worldwide average)”. The latency between HTTP requests, and also the limitation in web browsers in regards to how many parallel HTTP requests a web browser can make, vastly affects the loading time of a web page.

When it comes to CSS and JavaScript, the general consensus is to concatenate all files of the same type into one file, and then minify them. To complement that, Kyle Simpson have done some interesting experimenting with his LABjs, and he writes more about his thoughts in LABjs: why not just concat? how controlled parallel loading could also prove to be efficient.

That leaves us with images. Without a doubt, both the size and number of images used in a web page, although pretty to look at, definitely poses a threat to having a fast web site, and I thought we’d look at the alternatives for dealing with that.

CSS Sprites

CSS Sprites are when you combine a number of images into the same image file. You then use background-position in the CSS file to control what part of that image will be visible for a certain element. This way, instead of having a number of HTTP requests, there will be just one for a larger image file.

For instance, you can see this in action at Yahoo.com at the left hand side, with the icons in the list. Steve Souders has also created the excellent tool SpriteMe, in the form of a bookmarklet, that will analyze the current page to see which images you can combine, and also generate the images for the CSS Sprite. Another great alternative is the web site CSS Sprite generator.

There are a couple of downsides with CSS Sprites, though. One is that, depending on the design, it can become virtually impossible to combine some images, because their repeating pattern, reusage etc will prevent that. While the above mentioned tools are great, at the end of day, you always seem to end up manually tweaking your CSS Sprites images file(s) and CSS code.

Firefox engineer Vladimir Vuki?evi? has also written the interesting piece To Sprite Or Not To Sprite where he sheds some light on memory usage in web browsers and how large images aren’t always optimal.

So, at times CSS Sprites can be great, but they aren’t always the best choice.

Introducing base64-encoded Data URIs

Which leads us on to the highly interesting topic of base64-encoded Data URIs. For a more thorough explanation of what those are, I recommend reading Data URIs explained by Nicolas Zakas of Yahoo!. Generally, though, it’s about writing out binary files converted into data which describes the content.

What this means in practice is that in the HTML code or CSS file we can have the code for the contents, instead of just a reference to the file, which means that we completely eliminate that HTTP request. Just imagine having a web site full of images referenced, but none of them will cost one single HTTP request! 🙂

Let’s look at a real example of showing Smurfette via CSS.

Regular CSS background image

.smurfette { background: url(smurfette.png); }

Base64 Data URI as background image

.smurfette { background: url(data:image/png;base64,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); }

Comparing the alternatives

As you can see, the Data URI example is a lot of characters, but the beauty of it is that it describes the image inline, completely eliminating the need for a HTTP request! And sure, as you can see the file size will get bigger (especially in this example), but overall the result is much better than a huge number of HTTP requests. Besides, from my testing and reading about other peoples’ results, if you gzip your CSS file the resulting size is about the same as the regular image URL reference!

Web browser support

Data URIs are supported in:

Firefox 2+

Safari – all versions

Google Chrome – all versions

Opera 7.2+

Internet Explorer 8+

Internet Explorer…

As you can see, Internet Explorer does actually support Data URIs from IE 8! However, Microsoft, not to get astray from their long-standing tradition of doing half-ass implementations, only support data URIs smaller than 32 kilobytes. That might sound like a lot, but naturally it becomes a stick in your eye when you have larger images. For instance, in the web site I work on now, I have two images that were too large as Data URIs for IE 8, so I needed to include those two specific files exclusively for IE 8.

What about Internet Explorer versions older than IE 8 then? Actually, interestingly enough they support the MHTML format, which is an alternative way to accomplish the same thing for older IE versions. Stoyan Stefanov, also of Yahoo!, have written about this approach in MHTML – when you need data: URIs in IE7 and under and related problems in Vista and Windows 7 in Data URIs, MHTML and IE7/Win7/Vista blues.

There is some serious trickery, and limitations, when it comes to getting MHTML working. I know a number of people who used it, but in my tests, I actually never got it to work properly. Looking at general web site statistics, though, IE 6 and IE 7 usage steadily decreases all the time. If you want to solve it with MHTML, absolutely, but for me personally, I believe with offering the Data URI solution to all of the above-mentioned supported web browsers, I will still reach a good majority of the market, and, importantly, future web browsers.

Tools for encoding

There are a number of terminal-based tools to convert your images into the base64-encoded format, and you also have the option of online image to base64 converters. However, doing all this conversion (fairly) manually and then pasting the code into your code is quite tedious. There has to be a better way, right?

Right! Nicholas Zakas has created the outstanding tool CSSEmbed, which takes a CSS file as input, goes through it and encodes all image references to base64. This means that the action of changing all your image references in your CSS file to base64-encoded is a matter of seconds!

Just download the cssembed JAR file, put it wherever you like (placed in the same directory as the CSS file below for simplicity) and then call it like this:

java -jar cssembed-0.3.2.jar styles.css > styles-base64.css

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.

High-traffic web sites using Data URIs

By now, I hope you are as excited as me about this! Imagine removing about 2/3 of all your HTTP requests in a second, thanks to CSSEmbed! And this practice is not some future technology that we might use in five years, it’s here today! Just take a look at the thumbnails in a Google search for monkey and the search button in Yahoo! Search, for instance, and you will see what I’m talking about.

Therefore, I hope this have inspired you to get faster web pages without compromising one bit with the content!

Acknowledgements

Great thanks to Malte Ubl for suggestions and help, and to Mark Wubben for discussing base64-encoding alternatives.