start blog post

Exceptional Performance: Image Optimization

Image optimization should be a big part of tuning your website's performance. The largest components of a page are typically images, and unlike HTML, CSS, and JavaScript, images don't reap much (if any) benefit from being served gzipped. There's still a lot that can be done to speed up your images that don't involve any loss in quality.

YSlow Serious?

YSlow is a tool developed by Yahoo as a plugin for Firebug. It offers lots of information and advice that can help you target important aspects of your website's performance. YSlow evaluates your pages and displays a sort of report card based on a bunch of weighted evaluations. One "grade" it gives you that is not as useful for small- to medium-sized sites is Use a Content Delivery Network. However, you can tell YSlow not to count this grade in your overall page score by typing about:config in Firefox's address bar, creating the key extensions.firebug.yslow.pointsNotCDN and setting its value to 0. YSlow offers other features such as cache statistics, which shows what your visitors have to download the first time they hit your page, versus what they have to download on subsequent visits. Make sure the second column is as small as possible to offer loyal users a faster website.

Pretty pie charts! YSlow's cache statistics for this very page.

Smush.it

Smush.it is a great site that gets rid of metadata in your images, reducing their file sizes without reducing image quality. For some images, this can mean very significant savings. They even have extensions and bookmarklets that help you quickly and easily optimize an entire page at once. Very cool.

Diff'rent Strokes

Image format can play a major role in both size and quality. Choosing a format that suits the type of image you're making can drastically reduce the filesize. The YUI blog has a recent post that says basically everything I was going say here, but here's a quick summary:

  • JPG should be used for real-world photographs, despite its generation loss.
  • GIF should be used for animations, and for some pixel art GIF results in a smaller file size than PNG.
  • PNG (usually 8-bit) should be used for everything that's not covered by the other two formats.

Minimize HTTP Requests

It takes less time for your visitors to download one 100k file than it does to download four 25k files. HTTP requests add to the overall download time for your pages, so do everything you can to eliminate them.

  • CSS Sprites and image maps are methods of combining multiple images into a single file. One sprite and careful positioning can cut several requests, saving your visitors precious seconds.
  • favicon.ico — make one, and make it tiny. You should make your favicon as small as possible to improve cacheability. If you don't have one at all, browsers can attempt to request it again on every single one of your pages. Worse yet, when they don't find it they have to make a second request to get your 404 page. Making even a simple favicon will not only avoid those "double requests", and a cached icon will eliminate dozens of potential requests, saving loyal visitors time on every page.
  • Cacheability (which probably isn't a word) means making sure your visitors don't have to redownload the same images every time they come back to your site, or even as they navigate from page to page. Get the INode out of your ETags, set an Expires header date in the future, and make sure (only if you use ETags as mentioned) to unset the Last Modified header to make sure your images can be cached.
        # .htaccess file in your document root
        <IfModule mod_expires.c>
            ExpiresActive on
            ExpiresDefault "access plus one month"
        </IfModule>
        <FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|swf)$">
          FileETag -INode MTime Size
          Header unset Last-Modified
        </FilesMatch>
        

Maximize Parallel Downloads

Now that you've cut out unnecessary HTTP requests, it's time to make the remaining requests faster.

  • Flush early, flush often — no, that's not about bathroom etiquette. Flushing content to the browser immediately after the document head lets the browser fetch your CSS file while the rest of the page is processed, and flushing again before the scripts at the bottom of your page gives the impression of faster rendering while those scripts are fetched and executed.
        <!DOCTYPE ...>
        <html>
            <head>
            </head>
            <?php ob_flush(); flush(); ?>
            <body>
                ... <!-- page content -->
                <?php ob_flush(); flush(); ?>
                <script src=...>
            </body>
        </html>
        
  • Serve images from another subdomain — Browsers may be configured to download only two items at a time from a single host. If you serve plain text from www.yoursite.com and images from images.yoursite.com, those same browsers should be able to download four components at a time. Obviously this also depends on the structure of your page and your visitors' browser configuration. More details and spiffy graphs are at Maximizing Parallel Downloads in the Carpool Lane.

Before and After

Preload. Once your document finishes loading, start anticipating where your visitor will go next. Google and Yahoo each load additional components after their search homepages finish loading, because they can safely guess where you'll end up next (their search results page). For other sites it's not as easy to anticipate, but often you can use browser "down time" to prefetch components. Don't get too enthuastic about preloading, though, or you may just end up wasting bandwidth.

Postload. As Yahoo puts it, "What's absolutely required in order to render the page initially?". The rest of the content and components can wait. If you have some content split up into tabs or cards, only load the first item on startup. Load the rest of the content once the page is fully rendered. Don't make the visitor wait for content they can't use or see yet.

One Size Fits One

Don't scale images at render time via HTML or CSS. If your image is 100x100, your CSS should indicate as much. Don't scale a big image down, just resize it — otherwise the visitor still has to download the big image, but doesn't get the benefit of increased resolution. Scaling a small image up can save download time, but at the expense of image quality.

var tags = [, , ];

  • share this post:
  • email a friend
  • float this post
  • digg this post
  • share on stumbleupon
  • submit to technorati
  • tweet this post

end blog post