This is part 2 of Wicked Fast Websites, a three-part series that explores why web performance matters and what you can do about it.
We’re in the middle of a perfect storm. Websites are larger, devices are more varied and less predictable, and performance expectations are higher than ever. Today, you’ll learn some simple tools and techniques you can use to build high performance websites.
An aside: Today’s websites are five times bigger than in 2009. In fact, they’ve gotten 20-percent bigger this year alone. One of the easiest ways to improve the performance of your websites is to put them on a diet.
Markup Order Matters
When a browser accesses a webpage, it immediately begins reading and rendering the content. When it comes across external files likes images and videos, it begins downloading them, two at a time. This is really useful, because if you have a really large file, it doesn’t hold up the other files from being downloaded.
There are two exceptions to this process:
- CSS stops a browser from rendering content. Repaints are bad for performance, so the browser waits until it's finished downloading the styles before rendering any additional content.
Put your CSS at the top of your page, up in the
<head> because your stylesheet often relies on them.
The order of styles and scripts in your markup doesn’t make the page download content any faster, but it does help browsers start displaying it more quickly, and therefore appear faster.
Combine Similar Files
One of the biggest bottlenecks in page load time is in downloading the actual files for your site. Each HTTP request adds additional load time. How much time? According to Google:
Every time a client sends an HTTP request, it has to send all associated cookies that have been set for that domain and path along with it. Most users have asymmetric Internet connections: upload-to-download bandwidth ratios are commonly in the range of 1:4 to 1:20. This means that a 500-byte HTTP header request could take the equivalent time to upload as 10 KB of HTTP response data takes to download. The factor is actually even higher because HTTP request headers are sent uncompressed. In other words, for requests for small objects (say, less than 10 KB, the typical size of a compressed image), the data sent in a request header can account for the majority of the response time.
It’s actually faster for a browser to download one 300kb file than it is to download three 100kb files. By combining similar file types together—a process known as concatenation—you can improve page performance.
scripts.js file. Rather than loading separate CSS files for your base styles, small screens, bigger screens and so on, combine them all into a single stylesheet with media queries.
And don’t think you can cheat by using the
@import rule. That still requires additional HTTP requests.
Remove the Whitespace
One useful minification tool is Google PageSpeed Insights, a browser extension for Chrome and Firefox.
In your browser, open up Developer Tools and click on the “Page Speed” tab. Then click “Analyze.” You’ll be given a list of things you can do to improve your site performance.
One of the items on the list will be “Minify CSS.” Click it. Under “Suggestions for this page” is a link to “see optimized content.” Follow that to get a minified version of your CSS provided by Google.
The result is a tiny but rather unreadable stylesheet. Rather than overwriting your human-readable CSS, paste the minified code into a new file called
style.min.css and reference that in the header of your HTML. If you ever want to make updates, is as simple as removing the
.min and reminifying when you’re done.
scripts.js file, and put my minified code in
scripts.min.js. Minifying your markup gets a bit trickier, and results in less reduction in file weight, so you may choose not to follow that step.
If you’re using jQuery on your site, Google provides a hosted and minified version that’s 34-percent of the original size. An additional benefit of using the Google-hosted version of that a lot of developers use this technique, so there’s a good chance your visitor has jQuery cached in the browser already and doesn’t need to download it at all.
HTML5 Boilerplate uses a smart implementation of this that provides a local fallback if the Google CDN is unavailable:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.10.2.min.js"><\/script>')</script>
You’ll notice that the
http: is missing from the the URL. That helps avoid errors associated with encrypted domains.
Smarter Image Formats
Different image formats work better for different types of graphics.
PNG is a lossless image format, so it keeps graphics sharp and crisp (as opposed to the lossy JPG format). For icons and simple images with clean lines, they can actually be more lightweight than JPGs. But for photos and images with lots of visual noise, JPGs will be much smaller in size with comparable quality.
The JPG actually has multiple formats. The most common on the web is the baseline JPG. Baseline JPGs start rendering at the top, and build down as they go.
An alternative format that was popular a decade ago and is seeing a bit of a comeback is the progressive JPG. Progressive JPGs build in layers. Initially, the full image in low resolution is displayed, and as the image renders, it becomes increasingly crisp and clear.
While progressive JPGs are typically a little smaller than baseline, their real advantage is that they appear faster to the user because they display more content faster. And on smaller screens, the lack of clarity on initial renders may not even be as noticeable.
While all browsers display progressive JPGs, some browsers do a better job than others. For “non-supporting” browsers, the entire progressive JPG needs to download before it can be displayed, resulting in a worse experience than a baseline JPG.
Compress Your JPGs
Photos can add a lot of weight. A high-quality photo can weigh as much as 700kb or more. By compressing photos, you can reduce them down to less 100kb while maintaining image quality.
A JPG compression rate of 70 is considered high-quality for the web.
Smush Your Images
The metadata that photographs include—timestamps, color profiles, and such—can add quite a bit of weight. Smushing is the process of removing that metadata, and it can reduce the size of an image by more than 25-percent.
If you’re a Mac user, ImageOptim will smush your images without degrading the quality. It works for PNGs, JPGs, and GIFs.
Windows lacks a clear one-for-one counterpart, though their are a handful of products that work well for different image types. If you’re a Windows user, check out b64.io, a web-based, drag-and-drop optimizer that seems to work just as well as ImageOptim (hat tip to Chris Coyier).
Icon fonts take advantage of the CSS3
@font-face rule, and allow you to embed a font (kind of like webdings) on your site that contains all of your icons.
They offer a few advantages over image-based icons:
- They're lightweight.
- All of your icons are in a single file.
- They're styleable with CSS.
- Because they're a font, they're infinitely scalable, and look crisp on both regular and high-density displays.
- They're compatible all the way back to IE 5 (seriously).
There are two small considerations:
- Windows Phone 7 (running IE 9) lacks true
- Icons can only be one color.
The free IcoMoon app allows you to pick just the icons you need and even upload your own. There’s a lot to learn about icon fonts, so if you’re interested, check out my start-to-finish tutorial on using them.
If you still need to serve up small sets of images, you should consider using image sprites. Rather than using multiple image files, you can combine all of your images into a single file and embed it using the
background-image property, resulting in fewer HTTP requests.
Image sprites are useful if you need multi-color icons or Windows Phone 7 support, though their are some challenges in using them with high-density displays. They’re also a bit harder to maintain should you decide to add or remove an icon. If you’d like to use image sprites, the CSS Sprite Generator makes things a bit easier.
Web images need to look good on everything from low-powered phones and watches to big-screen TVs and high-density displays. But why should a smartphone get the same image as a big, high-density monitor?
Adaptive images are an approach to this challenge. By detecting the size of the display (and ideally bandwidth constraints), you can serve the right image size for the device. Unfortunately, there’s no great way to do this today, though there are a lot of people who are working on it.
I believe the most promising solution lies with a standards-based solution (the W3C has several in the works) that let’s the web developer offer the same images in multiple sizes, and let’s the browser decide which one best fits the user’s current needs.
Compress Your Site
Your server can actually compress your website files—a process known as gzipping—before sending them to the browser. This results in about a 70-percent reduction in website size.
On Apache servers, you can enable gzipping with a simple modification to your
.htaccess file. Learn how in this tutorial on GitHub.
Some web hosts use a slightly different method to implement gzipping. You can check if it’s working on your site using gzipWTF.
Set Expire Headers
Expire headers tell browsers to keep static assets stored locally so that a visitor’s browser doesn’t have to re-download them every time they visit your site.
This is also something that’s done using the
.htaccess file. To set expire headers, follow these instructions on GitHub.
- Markup order matters.
- Combine similar files.
- Remove the whitespace.
- Use smarter image formats.
- Compress your JPGs.
- Smush your images.
- Use icon fonts and image sprites.
- Consider adding adaptive images.
- Compress your site.
- Set expire headers.
These techniques can be implemented in about an hour, and make a big difference on site performance. You can test your site performance using the Pingdom Website Speed Test.