Optimizing Images: Chapter 10 - Even Faster Websites

by Stoyan Stefanov and Nicole Sullivan
Even Faster Web Sites book cover

This excerpt is from Even Faster Web Sites .

Souders and eight expert contributors provide best practices and pragmatic advice for improving your site's performance in three critical categories: JavaScript, in the network, and in the browser.

buy button

The single most important thing you can do to improve performance is put your site on a diet—take off (and keep off) all the bytes you put on under the stress of chasing the next killer feature. Optimizing images is one way to do just that. Historically, the question of which features to include was considered a business rather than an engineering decision, so page weight has rarely been discussed in performance circles, and yet it is extremely important to overall response time.

Response time for web pages is almost exactly correlated to page weight, and images tend to account for half of the size of typical web pages (see Figure 10.1, “Images as a percentage of page weight for the Alexa top 10 global web sites”). Most importantly, images are an easy place to improve performance without removing features. Often, we can make substantial improvements in the size of an image with little to no reduction in quality.

Figure 10.1. Images as a percentage of page weight for the Alexa top 10 global web sites

Images as a percentage of page weight for the Alexa top 10 global web sites

In this chapter, we focus on nonlossy optimizations, which result in a smaller overall file size with no loss in quality. Pixel for pixel, the visual quality of the original and final images is the same. The reduction in size often results from removing metadata, better compression of color or pixel information, or (in the case of PNG) removing chunks that are not necessary for the Web.

If you don’t optimize images, you send extra data over the wire that adds nothing to the user experience. It seems like a no-brainer to follow the practices we’ll recommend in this chapter, but image optimization falls in the blurry space between engineering and design, and has historically been a neglected part of the performance puzzle.

In this chapter, we’ll cover:

  • Characteristics of different image formats for the Web (GIF, JPEG, and PNG)

  • Automating lossless optimization

  • The AlphaImageLoader filter

  • Optimizing sprites

  • Other image optimizations

Two Steps to Simplify Image Optimization

Image optimization is simpler when it is broken down into two steps, each of which is owned by a different stakeholder in the creation of a web site:

  1. Optimizing images begins with a qualitative decision about the number of colors, resolution, or accuracy required for a given image. These changes are lossy optimizations that result in an overall loss of quality. The image might have fewer colors, or in the case of the JPEG format, less detailed encoding. Although 60% to 70% quality is the accepted standard for JPEG, some images or contexts may require more or less quality. For instance, glossy images of celebrities may require a larger file size than autogenerated charts or tiny thumbnails. These decisions are creative decisions and should be made by the designer, using tools such as the Save for the Web feature in Photoshop. The designer may also choose to do “spatial” or “zonal” compression—for example, choosing 80% quality for Brangelina’s face and only 30% quality for the night background.

  2. Once the quality choice has been made, use nonlossy compression to squeak the last bytes out of the image. Unlike the preceding step, this one begs for an engineering solution. Doing the same work by hand would be much more time-consuming. In fact, fantastic open source tools exist for optimizing images. You can write a script that goes over all of your image files, determines the type of each, and runs a utility to optimize the file.

Image Formats

The first step in producing optimal images is to understand the features of each of the three formats used on the Web today—JPEG, PNG, and GIF—and choosing the right one for each specific case. Let’s start the discussion of the different formats with just a few bits of background information.


This section discusses the traits of images that affect how you use them on the Web and that factor into your choice of a format.

Graphics versus photos

Both the image format you use and the ways to optimize it depend on which of the following categories the image falls into:


Examples of graphics are logos, diagrams, graphs, most cartoons, and icons. These images usually contain continuous lines or other sharp transitions in color. The number of distinct colors in a graphic is relatively small.


Photos usually have millions of colors and contain smooth color transitions and gradients. Imagine, for example, a picture of a sunset you take with your camera. An image of a painting (such as the Mona Lisa) is also closer to a photo than a graphic.

In terms of formats, GIFs are often used for graphics, whereas JPEG is the preferred format for photos. PNG comes in two kinds, of which palette PNG is even better suited for graphics than GIF.

Pixels and RGB

Images consist of pixels, where a pixel is the smallest piece of image information. Different color models can be used to describe a pixel, but the RGB color model is the one usually used for computer graphics.

In the RGB color model, a pixel is described based on the amount of red (R), green (G), and blue (B) it contains. R, G, and B are called components (a.k.a. channels), and the intensity of each component has a value from 0 to 255. The hexadecimal representation of the channel values, often used in HTML and CSS, ranges from 00 to FF. Mixing different intensities of the three channels gives you different colors. For example:

  • Red is rgb(255, 0, 0) or hex #FF0000.

  • Blue is rgb(0, 0, 255) or hex #0000FF.

  • A shade of gray will likely have equal parts of each color; for example, rgb(238, 238, 238) or hex #EEEEEE.

Truecolor versus palette image formats

Using the RGB color model, how many distinct colors can you represent in a graphic? The answer is more than 16 million: 255 * 255 * 255 (or 224) gives you 16,777,216 combinations. Image formats that can represent this many colors are called truecolor image formats; examples are JPEG and the truecolor type of PNG.

To save space when storing the image information in a file, one technique is to create a list of all the unique colors found in the image. The list of colors is called a palette (also called an index). Having the list of colors, you can represent the image by keeping track of which palette entry corresponds to each pixel.

The palette can contain any RGB value, but the most common palette image formats—GIF and PNG8—limit the number of palette entries to 256. This doesn’t mean you can pick from only 256 predefined colors. On the contrary, any of the 16+ million colors are up for grabs, but you can only have up to 256 of them in a single image.

Transparency and alpha channel (RGBA)

RGBA is not a distinct color model, but more of an extension to RGB. The extra component A represents alpha transparency and also has values from 0 to 255, although different programs and libraries define it as a percentage from 0% to 100% or values from 0 to 127. The alpha channel describes how much you can see through the image pixel.

Let’s say you have a web page that has a background pattern and a blue image on top of it. If a pixel in the image has zero alpha transparency, the background behind the image will not be visible. If the alpha transparency value is the maximum 100%, the pixel will not be visible at all and the background will “shine through.” A medium value of, say, 50% will let you see both the background and the pixel. Figure 10.2, “Examples of images with variable transparency produced using PHP with the GD library, which declares alpha values from 0 to 127” shows some examples.


When a large image downloads over a slow Internet connection, it is drawn as it arrives, one row at a time from top to bottom, so it grows down slowly. To improve the user experience, some image formats support interlacing, in which successive samples of the image are shown. Interlacing lets the user see a rough version of the image while waiting for the details, giving the psychological effect of eliminating the feeling that the page is delayed.

Figure 10.2. Examples of images with variable transparency produced using PHP with the GD library, which declares alpha values from 0 to 127

Examples of images with variable transparency produced using PHP with the GD library, which declares alpha values from 0 to 127

Characteristics of the Different Formats

With this background under our belts, let’s see how GIF, JPEG, and PNG differ.


GIF, an abbreviation for Graphics Interchange Format, is a palette image format. Here are some of its features:


GIF allows for a binary (yes/no) type of transparency—a pixel is either fully transparent (not containing a color) or fully opaque (containing a solid color). This means that alpha (variable) transparency is not supported; instead, one of the colors in the palette is marked to represent transparency, and transparent pixels are assigned that color. So, if your GIF has transparent pixels, this will “cost” you one palette entry.


The GIF format supports animation. An animated image consists of a number of frames; it’s like having several images contained in the same file. GIF animations are generally perceived as annoying because of their abuse in the early years of the Web, when they were used for blinking text, rotating @ signs, and so on. They still have some application today; for example, for ad banners (although this is mainly a Flash domain now) or little “Loading…” indicators in Rich Internet Applications (RIAs).


The GIF format is nonlossy, which means you can open a GIF, do some editing, and save it without losing quality.

Horizontal scanning

When writing a GIF file, a compression algorithm (called LZW) is used to reduce the file size. When compressing the GIF, the pixels are scanned horizontally, top to bottom. This results in a better compression when you have areas of horizontally repeating colors. For example, a 500 × 10-pixel image (width: 500px; height: 10px) containing stripes—meaning horizontal lines of the same color—will have a smaller file size than the same image rotated to 90 degrees (width: 10px; height: 500px) when the stripes become vertical.


GIF supports optional interlacing.

The 256-color limit for GIFs makes them unsuitable for photos, which usually require a much greater number of colors. GIFs are better suited for graphics (icons, logos, diagrams), but as you’ll see later in this chapter, PNG8 is a superior format for graphics. Therefore, you should usually use GIFs only for animation.

There used to be a patent issue with LZW, the lossless data compression algorithm used by the GIF format, but the patents expired in 2004, so GIF can be used freely now.


JPEG stands for Joint Photographic Experts Group, the organization that developed the standard. JPEG is the de facto standard for storing photos. This format reduces the information required to show a picture through techniques that take into account the human eye’s perception of color and light intensities, so it can store high-resolution images in greatly compressed files. Here are some of its features:


JPEG is a lossy format that accepts a user-specified quality setting, which determines how much image information is lost. The quality values range from 0 to 100, but even a value of 100 will result in some quality loss.

When you do multiple edits of the same image, it’s best to use a nonlossy format to store the intermediate results and then save as JPEG once you’re done with the changes. Otherwise, you’ll lose some quality every time you save.

A few operations can be performed losslessly, such as:

  • Rotation (only to 90, 180, or 270 degrees)

  • Cropping

  • Flipping (horizontal or vertical)

  • Switching from baseline to progressive and vice versa

  • Editing image metadata

The last of these operations is particularly valuable for our purposes. We’ll exploit it later to automate the optimization of JPEGs.

Transparency and animation

JPEG doesn’t support transparency or animation.


In addition to the default baseline JPEG, there’s also a progressive JPEG, which supports interlacing. Internet Explorer doesn’t render the progressive JPEG in stages, but it successfully displays the whole image once it arrives.

JPEG is the best format for photographic images on the Web and is also widely used in digital cameras. It is not suitable for graphics, however, because of the artifacts of the lossy compression around lines or other sharp transitions of color.


PNG (Portable Network Graphics) was created to address shortcomings of the GIF format and its patent complications. In fact, the joke goes that PNG is a recursive acronym that stands for “PNG is Not GIF.” Here are some of its features:

Truecolor and palette PNGs

The PNG format has several subtypes, but they can roughly be divided into two: palette PNGs and truecolor PNGs. You can use palette PNGs as replacements for GIFs, and you can use truecolor PNGs instead of JPEGs.


PNG supports full alpha transparency, although there are two quirks in Internet Explorer version 6 that we’ll describe later.


Although experiments and actual implementations exist, currently there’s no cross-browser support for animated PNGs.


Unlike JPEG, PNG is a nonlossy format: multiple edits do not degrade quality. This makes the truecolor PNG a suitable format for storing intermediate stages of editing a JPEG.

Horizontal scanning

Like GIFs, PNGs that have areas of horizontally repeating colors will compress better than those with vertically repeating colors.


PNG supports interlacing and uses an algorithm that is superior to GIF; it allows for a better “preview” of the actual image, but interlaced PNGs have bigger file sizes.

More About PNG

Let’s take a look at a few more details that will give you a better understanding of the PNG format.

PNG8, PNG24, and PNG32

You might come across the names PNG8, PNG24, or PNG32. Let’s clarify their meaning:


Another name for palette PNG


Another name for truecolor PNG that has no alpha channel


Another name for truecolor PNG with alpha channel

There are other variations, such as grayscale PNGs with and without alpha, but they are used much more rarely.

Comparing PNG to the other formats

It’s clear that GIFs are designed for graphics, JPEGs for photographs, and various types of PNGs for both. This section compares PNG to the other formats and offers some extra details about PNG.

Comparison to GIF

Except for animation support, palette PNGs have all the features of GIFs. In addition, they support alpha transparency and generally compress better, resulting in smaller file sizes. So, whenever possible, you should use PNG8 rather than GIF.

One exception is that very small images with very few colors might compress better as GIFs. But such small imagery should be part of a CSS sprite, because the “price” of an HTTP request will greatly outweigh the saving of a few bits. Chances are the sprite image will compress better as a PNG.

Comparison to JPEG

When you have an image with more than 256 colors, you need a truecolor image format—a truecolor PNG or a JPEG. JPEGs compress better and, in general, JPEG is the format for photos. But since JPEGs are lossy and there are artifacts around sharp transitions of color, there are cases when a PNG is better:

  • When the image has slightly more than 256 colors, you might be able to convert the image to PNG8 without any visible quality loss. It’s quite surprising how sometimes you can strip out more than 1,000 colors and still not notice the difference.

  • When artifacts are unacceptable—for example, a color-rich graphic or a screenshot of a software menu—a PNG is the preferred choice.

PNG transparency quirks

Two quirks in Internet Explorer 6 are related to PNG and transparency:

  • Any semitransparent pixels in a palette PNG appear as fully transparent in Internet Explorer 6.

  • Alpha transparent pixels in a truecolor PNG appear as a background color (most often gray).

The first issue means PNG8 behaves like GIF in Internet Explorer 6. This is not so bad and still allows you to select PNG instead of GIF for all your graphical images. PNG8, therefore, offers “progressively enhanced” semitransparent images that look great in all modern browsers and degrade to GIF-like transparency in Internet Explorer 6.

The second issue is a little more serious and there are various workarounds that boil down to the use of the proprietary CSS property AlphaImageLoader or the use of VML. As you’ll see later in this chapter, AlphaImageLoader comes at a cost in performance and user experience and you should avoid it when possible. The VML workaround has the drawback of adding extra markup and code. In conclusion, always try to achieve the design using PNG8.

PNG8 and image editing software

Unfortunately, most image-editing programs, including Photoshop, can only save PNG8 with binary transparency. One notable exception is Adobe Fireworks, which has excellent alpha transparency support. There are also command-line tools such as pngquant and pngnq that allow you to convert truecolor PNGs to palette PNGs.

Here’s an example of a pngquant command, where the number 256 specifies the maximum number of colors in the palette:

pngquant 256 source.png

Automated Lossless Image Optimization

Now that you know about the different image formats, let’s see how you can optimize your images. The beauty of the process you’re about to see is that:

  • It’s automated and doesn’t require human interaction.

  • All operations are lossless, so you don’t have to worry that the image quality will degrade.

  • It uses freely available command-line tools.

Each image type requires different handling, but it’s usually predictable and easy to automate in a script. This section discusses the following tasks:

  • Crushing PNGs

  • Stripping JPEG metadata

  • Converting single-image (nonanimated) GIFs to PNGs

  • Optimizing GIF animations

Crushing PNGs

PNGs store image information in “chunks.” This makes the format extensible because you can add more functionality to it using custom chunks, and programs that do not understand your new extensions can safely ignore them. But most of the chunks are not needed for web display, and you can safely remove them. An additional benefit is that stripping the so-called gamma chunk actually improves the cross-browser visual results, because each browser treats gamma corrections slightly differently.


Our favorite tool for PNG optimization is pngcrush. You can run it like this:

pngcrush -rem alla -brute -reduce src.png dest.png

Let’s take a look at the options:

-rem alla

Removes all chunks except the one controlling transparency (alpha).


Tries more than 100 different methods for optimization in addition to the default 10. It’s slower and most of the time doesn’t improve much. But if you’re doing this process offline, you can afford the one or two more seconds this option takes, in case it finds a way to cut the image size further. Remove this option in performance-sensitive scenarios.


Tries to reduce the number of colors in the palette, if possible.


The source image.


The destination (result) image.

Other PNG optimization tools

Pngcrush hits a pretty good middle ground that balances execution speed against optimization results. But if you want to achieve the best possible results and you’re prepared to spend a little more time on optimization, you can try some of the other tools. Results vary, depending on the image. You can even run all the tools in succession.

Notable tools include:


Binary-only, Windows, closed source


Cross-platform, open source, command-line interface


Windows, open source, GUI and command-line interfaces

One “heavy-duty” tool is also available: PNGslim. It’s a batch file for Windows that runs a number of other tools. Its main activity is to run PNGOUT hundreds of times with different options. PNGOUT is the slowest of all the tools we’ve tried, so you should be prepared to allow PNGslim plenty of time to run—sometimes hours to optimize a single file.

Stripping JPEG Metadata

JPEG files contain metadata such as the following:

  • Comments

  • Application-specific (e.g., Photoshop) internal information

  • EXIF information such as camera make and model, the date the photo was taken, the geolocation of the photo, thumbnails, or even audio

This metadata is not used for image display and can safely be removed. Metadata handling, luckily, is one of the lossless JPEG operations mentioned earlier in this chapter, so you can remove the unneeded parts of the file without losing visual quality.

A tool called jpegtran does the transformation on the command line:

jpegtran -copy none -optimize src.jpg > dest.jpg

The options in this example are:

-copy none

Instructs that no meta information should be carried over


Causes jpegtran to optimize the Huffman tables used for compression


Your image before optimization


The optimized file

The command writes to standard output, so to create the final file, this example just redirects output to a file named dest.jpg.


Strip meta information only from images you own. By stripping metadata from someone else’s JPEG, you might also strip any copyright or authorship data, which is illegal.

Jpegtran takes an all-or-nothing approach to handling metadata. For more fine-grained metadata editing, use ExifTool.

Converting GIF to PNG

As we discussed, the PNG8 format supports everything that GIF does, so converting a GIF to PNG8 should result in no visible changes. You can use ImageMagick to do the conversion from the command line as simply as:

convert source.gif destination.png

You can also force the PNG8 format by using:

convert source.gif PNG8:destination.png

This is probably not necessary, since GIFs are likely to be converted to PNG8 anyway. ImageMagick picks the appropriate format based on the number of colors.

Once you’ve converted the GIF to PNG, don’t forget to crush the PNG result (as shown earlier in this chapter).

You can also use ImageMagick’s identify utility to programmatically determine whether the GIF file contains an animation. For example:

identify -format %m my.gif

This command will simply return “GIF” for nonanimated GIFs. For GIF animations it will return a string such as “GIFGIFGIF…” repeating “GIF” once for every frame. If you’re running a script to convert files, checking for the presence of “GIFGIF” in the first six-character substring of the output will let you know you’re dealing with an animated file. In that case, you can skip to the next step.

Optimizing GIF Animations

Now that all your single-image GIFs are PNGs, your PNGs are crushed, and your JPEGs are optimized, the last things left to optimize are the GIF animations. One tool that can help you is Gifsicle. Since the animations consist of frames and some parts of the image don’t change from one frame to another, Gifsicle optimizes animations by removing the duplicate pixel information from successive frames. The way to run it is:

gifsicle -O2 src.gif > dest.gif


Smush.it is an online tool for image optimization, created by the authors of this chapter. It does what we just described in the previous four sections, applying lossless image compression to a variety of file types. Smush.it has a convenient Firefox extension companion that allows you to visit any page and optimize all the images on that page in one shot. You can always check how much you can save by following these steps.

Do note that Smush.it underperforms with JPEGs because it doesn’t strip the JPEG metadata, since we don’t want to involuntarily strip copyright information and “orphan” a JPEG. If you roll out your own “smushing” tool using the techniques and tools described earlier and you’re sure it’s appropriate to remove the metadata, do so using jpegtran’s –copy none option.

Progressive JPEGs for Large Images

When reviewing the different file formats, we mentioned that there are progressive JPEGs that render progressively in the browser, allowing the user to see a low-resolution version of the image while the file is still being transferred. The question is whether progressive JPEGs are smaller or bigger than nonprogressive equivalents.

After experimenting with more than 10,000 images chosen at random from the Web using the Yahoo! image search API, we’ve reached the conclusion that you cannot tell for sure. In fact, results can be all over the map. But a trend did emerge: images bigger than 10 KB usually compress better as progressive JPEGs. Smaller images are better as nonprogressive, baseline JPEGs. Figure 10.3, “Relationship between file size (X) and the benefit of progressive JPEGs. The y-axis shows the difference between the file size of the baseline image and the progressive image; the greater the Y value, the better it is to use progressive encoding” summarizes our findings, charting the original file size against the difference caused by optimization. The graphic ends at 30 KB, but the trend remains flat, meaning that the benefit of progressive encoding increases with file size.

Figure 10.3. Relationship between file size (X) and the benefit of progressive JPEGs. The y-axis shows the difference between the file size of the baseline image and the progressive image; the greater the Y value, the better it is to use progressive encoding

Relationship between file size (X) and the benefit of progressive JPEGs. The y-axis shows the difference between the file size of the baseline image and the progressive image; the greater the Y value, the better it is to use progressive encoding

Alpha Transparency: Avoid AlphaImageLoader

Much sought after in the world of web design, cross-browser alpha transparency is harder to achieve than you might expect. The PNG specification was written more than a decade ago, but lousy browser implementation means we’re still looking for the one perfect solution. Support for truecolor PNG has evolved very slowly. Internet Explorer 6 still has significant market share, but it suffers from serious technical limitations in handling PNG alpha transparency.

In this section, we’ll take a closer look at alpha filters, which force support for alpha transparency in older versions of Internet Explorer. In particular, Internet Explorer offers a filter called AlphaImageLoader that has become quite popular. Drawing on experimentation and practice at Yahoo!, and backed up by hard data, we’ve concluded that you should not use AlphaImageLoader to fix Internet Explorer 6 transparency problems. We’ll explain why this is so and show practical examples of progressively enhanced PNG8 to work around these limitations.

Effects of Alpha Transparency

As you saw earlier, transparency comes in two flavors. The first is a kind of binary transparency: each pixel is either fully transparent or fully opaque. The second is alpha transparency, which allows you to have variable levels of opacity.

The lack of support for true alpha transparency in Internet Explorer 6 has been a challenge for web developers who wanted to have smooth transitions and drop shadows. For instance, the lefthand side of Figure 10.4, “Alpha and binary transparency in My Yahoo! weather icons; the squares are a typical pattern used in image editing programs to denote transparency” shows an effect we’d like to achieve (partial transparency that allows some of the background to show through); the righthand side shows the inclusion of the background color (in this case, white), which we have to live with when only binary transparency is supported. Solid-color backgrounds work equally well for both image formats, as they allow the binary transparent image to perfectly mimic the effect of full alpha transparency. However, the same icon could not be reused if the background color was not identical.

Figure 10.4. Alpha and binary transparency in My Yahoo! weather icons; the squares are a typical pattern used in image editing programs to denote transparency

Alpha and binary transparency in My Yahoo! weather icons; the squares are a typical pattern used in image editing programs to denote transparency

Typically, alpha transparency is used in cases where the background is variable, as in a photograph, graphic, or gradient. In these cases, it is harder to fall back on simulating transparency because it is impossible to be certain which colors will be behind a given portion of the image.

Perfect alpha transparency allows the image of the cloud to be put over any background and it will display beautifully. Binary transparency (on the right side of Figure 10.4, “Alpha and binary transparency in My Yahoo! weather icons; the squares are a typical pattern used in image editing programs to denote transparency”) requires a slightly more creative approach: the designer is forced to approximate transparency by including a small portion of the background color around the graphic.

Gradient backgrounds (see Figure 10.5, “Gradients and transparency”) require more careful attention to the edges of the cloud overlay. If too much of the fluffy edge or drop shadow is left around the image, it will look too dark in some areas and too light in others. It helps to leave as little background color as possible. In Figure 10.6, “A real-world example that shows the weather icon above a variable background on the My Yahoo! page; the design has all of the challenges discussed: gradients, solid colors, and patterns”, it’s obvious that too much color was kept around the graphic. The mid-tone is too light at the top of the image and too dark at the bottom.

Figure 10.5. Gradients and transparency

Gradients and transparency

Figure 10.6. A real-world example that shows the weather icon above a variable background on the My Yahoo! page; the design has all of the challenges discussed: gradients, solid colors, and patterns

A real-world example that shows the weather icon above a variable background on the My Yahoo! page; the design has all of the challenges discussed: gradients, solid colors, and patterns

Mountaintop corners

Another example is the ubiquitous rounded corner module. It is important to avoid including the background color of the module and the contour in one image because combining them will drastically increase HTTP requests. Rather than having one image for the contour that can be combined with multiple backgrounds, you will have many images representing all the possible combinations.

Separating contour and page background colors from the block background color or image allows for scalable CSS. However, it is interesting to note that separating the two requires a very careful selection of pixels and reliance on the eye’s tendency to smooth transitions. Dan Cederholm first wrote about this in his article “Mountaintop Corners” for A List Apart.

The difference between the two dark blocks in the module in Figure 10.7, “Binary and alpha transparency in rounded corner modules” may seem subtle, but when there is a high contrast between module, background, and foreground colors, the edge can seem “chewed off” rather than completely smooth. To achieve a uniform look and feel across browsers, developers began to use the AlphaImageLoader filter for Internet Explorer.

Figure 10.7. Binary and alpha transparency in rounded corner modules

Binary and alpha transparency in rounded corner modules


Internet Explorer does not natively support alpha transparency. Proprietary filters are used to fill the gap; however, the performance costs of this choice are significant. To understand the drawbacks of the method, let’s look at what not to do (see Example 10.1, “Using AlphaImageLoader to add rounded corners to PNGs”).

Example 10.1. Using AlphaImageLoader to add rounded corners to PNGs

.myModule .corner{
  background-image: url(corner.png);
  _background-image: none;

In Example 10.1, “Using AlphaImageLoader to add rounded corners to PNGs”, the initial underscores are a hack that causes the attributes to be applied only to versions of Internet Explorer older than version 7:

  • The _background-image attribute removes the original background, corner.png.

  • The _filter attribute reloads the same image using Microsoft’s AlphaImageLoader filter.

Only Internet Explorer 6 (or earlier) requires this hack. Internet Explorer 7 and later support alpha transparency natively, as do Firefox, Safari, and Opera. All these browsers ignore the rules with initial underscores, because the properties simply aren’t recognized.


If you forget to use the underscore hack, Internet Explorer 7 will use the filter despite having native support for alpha transparency.

Problems with AlphaImageLoader

There are both maintenance costs and direct performance costs associated with using alpha filters:

Code forking

Even the minimal amount of code forking in the prior example is dangerous from a maintenance point of view. When we write exceptions to CSS rules, the files tend to grow over time. Also, assuming we were using a CSS sprite to reduce HTTP requests, as recommended in High Performance Web Sites, background-position would not be supported when the alpha filter is used. In this case, the clip property is often used to simulate background image positioning in Internet Explorer.

Freezing the browser

When an alpha filter is applied, the page does not render progressively. The user will see a blank page until all the necessary components are downloaded. Page elements can still be downloaded in parallel, but the display will be blocked because Internet Explorer will not render anything until every last bit of CSS comes down the wire, and the CSS has a dependency on a filtered image. (For more information about rendering, see http://www.phpied.com/rendering-styles.) If you have several AlphaImageLoader filters on the page, they are processed serially, multiplying the problem. If you have five images, each delayed 2 seconds on the server, the browser freezes for a total of 10 seconds.

Increased memory consumption

Another negative effect of using AlphaImageLoader is the increase in memory that is required to process and apply the filters. These days we might be tempted to think our visitors’ computers have a virtually inexhaustible supply of memory, but that might not be the case for older computers, which are the ones more likely to run Internet Explorer 6 and earlier.

All this overhead applies to the image every time it appears on the page because the filter doesn’t change the image, but rather the HTML element to which the style is applied. If a sprite is used on 20 HTML elements on the page, there isn’t one performance penalty, but 20! Furthermore, each element is processed synchronously in a single UI thread. Often, this filter is used for “play” buttons that overlay video (see Figure 10.8, “Video player at Yahoo! Search that had the alpha transparency from the “play” button removed, to improve performance”). In this case, any performance penalty will be assessed for each video on the page.

Figure 10.8. Video player at Yahoo! Search that had the alpha transparency from the “play” button removed, to improve performance

Video player at Yahoo! Search that had the alpha transparency from the “play” button removed, to improve performance

In the wild: A Yahoo! Search case study

Lab tests are an excellent way to estimate the performance impact of code changes, but there’s nothing like testing an idea in the wild, with millions of requests coming from real users and their myriad browser configurations, geographic locations, connection speeds, hardware, and operating systems.

Based on lab tests, we estimated the performance “price” of the AlphaImageLoader filter to be approximately eight milliseconds per HTML element on which the filter is applied. Previously, the search team used a truecolor PNG and filter for their main sprite, which appeared 12 times in the page. Therefore, we expected approximately a 96-millisecond improvement, but we were eager to see whether a real user test would replicate our results.

The experiment compared two identical search results pages, one with the AlphaImageLoader filter and the other without. The results set comprised two distinct populations, which showed a 50- to 100-millisecond improvement. The response time for users of Internet Explorer 6 showed a 100-millisecond improvement, whereas the response time for users of Internet Explorer 5 showed a 50-millisecond improvement.

A 100-millisecond improvement (one-tenth of a second) seems small, but Amazon experimental data showed that a 100-millisecond increase in response time correlated to a 1% drop in sales. Understanding the direct link between revenue and performance can help justify the minimal investment required to switch from truecolor PNG to PNG8.

Based on this experiment, we recommend that you avoid AlphaImageLoader whenever possible. How can you avoid it? In the next section, we’ll show some techniques to avoid using a filter altogether.

Progressively Enhanced PNG8 Alpha Transparency

If you’ve decided you just have to have alpha transparency, but you don’t want the performance penalty associated with Microsoft’s proprietary alpha filters, you can apply progressive enhancement to PNG8. This creates an image that uses alpha transparency where it’s available, but doesn’t rely on it. Follow these steps to achieve the best result:

  1. Create a binary transparency image that uses only fully opaque or fully transparent pixels.

  2. Write the CSS necessary to use the image.

  3. Verify that the image works well without alpha transparency.

  4. Add in the partially transparent pixels that will be displayed by better browsers. You can do this by layering the two image formats in Photoshop or your tool of choice, and saving the output as a separate file. To save the final image as PNG8 with alpha transparency you will need to use Fireworks or a command-line tool such as pngnq. We don’t suggest allowing the software to autoconvert from truecolor PNG to PNG8, as the binary-transparent version is unlikely to be of acceptable quality.

To learn more about progressively enhanced PNG8, read Alex Walker’s SitePoint article, “PNG8—The Clear Winner”.


You can use PNG8 to progressively enhance images for which there is a clear binary transparent fallback. An image that has no fully opaque pixels would be rendered completely transparent by Internet Explorer 6.

For example, PNG8 progressive enhancement could be used on modules that overlay a variable background, such as the drop shadow popover above the Yahoo! Travel map shown in Figures 10.9 and 10.10.

Figure 10.9. Internet Explorer getting a simplified version with a clean 3-pixel border

Internet Explorer getting a simplified version with a clean 3-pixel border

Figure 10.10. Better browsers such as Internet Explorer 7 and 8, Firefox, Safari, and Opera also get a drop shadow

Better browsers such as Internet Explorer 7 and 8, Firefox, Safari, and Opera also get a drop shadow


The human eye is very sensitive to variations in silhouette because humans identify objects, especially people, based on shape. Pay close attention to the edges of graphics. Mistakes are more noticeable when they affect the outline of an icon or image.

Optimizing Sprites

Dave Shea coined the term CSS sprites to refer to a process of combining multiple background images into one larger image and using background position to show or hide only a portion of that image in an HTML element (http://www.alistapart.com/articles/sprites/). The technique was later used by Yahoo! to improve performance by reducing the number of HTTP requests for the tiny icons on Yahoo!’s home page. There are two approaches to optimizing sprites: the “everything and the kitchen sink” approach and the modular object-oriented approach. To figure out which is best for your site, ask the following questions:

  • How many pages does your site have?

  • Is your site modular? (Hint: it should be!)

  • How much time can your team spend on site maintenance?

The answers can help you make the traditional trade-offs between the number of sprite(s), the maintenance cost, and the total number of unique pages. You can have any two, but not all three (see Figure 10.11, “The sprite dilemma: choose any two”).

Figure 10.11. The sprite dilemma: choose any two

The sprite dilemma: choose any two

Über-Sprite Versus Modular Sprite

If a site has very few pages, it is best to sprite everything in the site into one über-sprite that includes all the images used on the site. Google uses an über-sprite for its search results page, as shown in Figure 10.12, “Google Search has only two pages; thus, it can have an über-sprite without significant maintenance costs”.

Figure 10.12. Google Search has only two pages; thus, it can have an über-sprite without significant maintenance costs

Google Search has only two pages; thus, it can have an über-sprite without significant maintenance costs

On the other hand, if your site has more pages, you need a different sprite strategy or the maintenance costs will be very expensive. The goal is to make it easy to remove stale modules from your site; otherwise, a once-performant site will become clunky. You can achieve this by spriting together images that belong to the same object. For example:

  • All four corners from one rounded corner box

  • The left and right sliding doors of your module headers

  • The two to four images that make up a button

  • Tab states such as current, hover, and normal

In a modular approach, these sprites would not be combined with other sprites.

Highly Optimized CSS Sprites

Sometimes optimizing sprites is more complex than optimizing images. Diverse resources combined in one sprite may be harder to compress well. Following these best practices will make your sprite as small as possible:

  • Combine like colors; for example, sprite icons with a similar color palette.

  • Avoid unnecessary whitespace, making images easier to process on mobile devices.

  • Arrange elements horizontally instead of vertically. The sprite will be slightly smaller.

  • Limit colors to stay within the 256-color limit of PNG8.

  • Optimize individual images, and then the sprite. Color reduction will be easier with a limited palette.

  • Reduce anti-aliased pixels via size and alignment. If an icon is slightly off-square, you can often reduce the anti-aliased pixels by aligning the image horizontally or vertically.

  • Avoid diagonal gradients, which cannot be tiled.

  • Avoid alpha transparency in Internet Explorer 6 or quarantine images that require true alpha transparency in a separate sprite.

  • Change the gradient color every two to three pixels, rather than every pixel.

  • Be careful with logos. They are very recognizable, so even small changes are likely to be noticed.

Other Image Optimizations

The remainder of this chapter discusses some additional image-related optimizations that can help your pages load faster. These concern how you use the image files rather than the images themselves.

Avoid Scaling Images

Unnecessary download overhead occurs when a 500 × 500-pixel image is scaled down in the HTML, like so:

<img src="image.jpg" width="100" height="100" alt="my image" />

This way, you cause the browser to scale down the image and show a smaller 100 × 100-pixel version of it. But the browser still needs to download the big image. You can achieve significant savings if you resize the image on the server side and serve the smaller version. As an additional selling point, be aware that some browsers don’t do as good a job at scaling down as, for example, ImageMagick does, so the result of forcing the browser to do the scaling is degraded image quality and bigger downloads.

Crush Generated Images

If you’re building a reporting application or module, chances are you’ll need to generate different graphs or charts on the fly. When you generate those types of images, keep in mind the following two points:

  • It is advisable to choose PNG over GIF, PNG8 being most preferred.

  • Don’t forget to crush the result before serving it.

An image found in the Google Chart API documentation makes a good example (see Figure 10.13, “An example generated graph image”). If you’re not familiar with it, Chart is an excellent API that allows you to generate graphs by passing arguments in the URL. Let’s take a look at how this service can be improved to generate images that are smaller.

Figure 10.13. An example generated graph image

An example generated graph image

Figure 10.13, “An example generated graph image” contains 1,704 colors, and the file size is 17,027 bytes. Two simple optimizations reduce the file size by more than half:

  • Running this image through pngcrush results in an image that is 12,882 bytes, a savings of 24% with no loss in quality.

  • Going one step further to convert the image to PNG8 using pngquant removes about 1,500 colors that the viewer doesn’t notice. The new file size is 7,710 bytes, a savings of 55% from the original.

An additional benefit from writing the generated images to disk and crushing them is that when a second request for the same image arrives, you don’t need to regenerate the image; you can serve the one that has already been cached and optimized.

Here is a simple piece of code that implements this advice using PHP with the GD image library:

header ('Content-type: image/png');

// name of the image file
$cachedir = 'myimagecache/';
$file = $cachedir . 'myimage.png';

// if in the cache, serve
if (file_exists($file)) {
    echo file_get_contents($file);

// new GD image
$im = @imagecreatetruecolor(200, 200);
// ... the rest of the image generation ...
imagepng($im, $file); // save
imagedestroy($im);    // cleanup

// crush the image
$cmd = array();
$cmd[] = "pngcrush -rem alla $file.png $file";
$cmd[] = "rm -f $file.png";
exec(implode(';', $cmd));

// spit out the new image
echo file_get_contents($file);

Another option, instead of reading the file with file_get_contents, is to use a redirect to point the browser to the new location. Add an Expires: header for browsers that support redirect caching, because they’ll reuse the image instead of downloading it on subsequent visits.


Favicons are those small images named /favicon.ico that sit in the web root and are displayed next to the URL in the browser’s address bar (see Figure 10.14, “Wikipedia favicon”).

Figure 10.14. Wikipedia favicon

Wikipedia favicon

This page component is often ignored because it’s small and supposedly cached. But caching is not as universal as we often think. This is true for any type of component, and favicons are no exception. Yahoo! Search noticed that it serves its favicon to 9% of all page views.

There are several points regarding favicons that significantly improve performance:

  • Make sure to create a favicon. Since the browser will request this file anyway, there’s no reason to return a 404 Page Not Found error, especially if your 404 handler consumes a database connection or other expensive resources.

  • Consider adding an Expires: header when serving favicons. You cannot afford to cache “forever” if you serve the file from /favicon.ico because you cannot rename the file if you decide to change it. But you can still cache for several months or even a year. Check the last modification date of your favicon file for an idea of how often you usually change it. And, if an emergency should arise, you can change the file name using a <link> tag, as explained next.

  • You have an option to include the favicon using a <link> tag in the head. This way, you control the URL requested by the browser, as opposed to the predefined /favicon.ico:

    <link rel="shortcut icon" href="http://CDN/myicon.ico" />

    This is great, because you can serve the favicon from a CDN and cache it “forever,” sharing the same file among all your sites.

    Be aware of one trade-off, though: if you do it this way, Firefox will request the favicon early in the waterfall, as opposed to at the very end after all other components are downloaded. On the other hand, if you serve the file from /favicon.ico, there’s no reason to add the <link> tag.

  • Make the icon small. The ICO format can contain several images of different dimensions; for example, 16 × 16, 32 × 32, and so on. This will increase the file size of your icon, so it’s best to use only one 16 × 16 image. This generally results in a file size of about 1 KB. As a rule of thumb, if your icon is bigger than 1 KB, you have room for improvement.

  • Optimize the file with the free Windows utility called Pixelformer, experimenting with different palette sizes.

Apple Touch Icon

Similar to favicons are so-called Apple touch icon files used by iPhone/iPod devices. An Apple touch icon is just a PNG file in the root of your web server, 57 × 57 pixels in size, called apple-touch-icon.png. Again, if you want to serve this icon from a CDN and add a far-future Expires: header to it, you can use a <link> tag, like so:

<link rel="apple-touch-icon" href="http://CDN/any-name.png" />

Desktop browsers request this file much less often than they request favicons; the iPhone client will ask for it only when the user adds your page to his home screen.


In this chapter, you familiarized yourself with quite a few topics related to images, and you’re now better prepared to ace your next image optimization project. Let’s rehash some of the highlights:

  • Start by choosing the appropriate format: JPEG for photos, GIF for animations, and PNG for everything else. Strive for PNG8 whenever possible.

  • Crush PNGs, optimize GIF animations, and strip JPEG metadata from the images you own. Use progressive JPEG encoding for JPEGs more than 10 KB in file size.

  • Avoid AlphaImageLoader.

  • Use and optimize CSS sprites.

  • Create modular sprites if your site has more than two to three pages.

  • Don’t scale images in HTML.

  • Generated images should be crushed, too. Once generated, they should be cached for as long as possible. Convert images to PNG8 and determine whether 256 colors is acceptable.

  • Don’t forget favicons and Apple touch icons. Even if you don’t refer to them in your HTML markup, they are still page components and should be small and cacheable.

If you enjoyed this excerpt, buy a copy of Even Faster Web Sites .