Performance Calendar » PNG that works

Once you sprite your images, the next step is to compress them as much as possible. PNG is a great format for this, but…

Yes, it does! No, it doesn’t! Which PNG?

PNG supports various combinations of color depth, transparency and color correction. Some combinations work perfectly with every piece of software produced in the last decade, and some more esoteric features are practically useless.

GIF-like PNG images with simple transparency are supported in all browsers (even as old as IE4) without any hacks, so whenever you can use GIFdon’t. Use PNG instead.

You’ll get the same quality and compatibility as GIF, but a smaller file size.

24-bit PNG files have perfect quality, but perfection costs a lot of bandwidth. Even though they work in all browsers, don’t use them.

When you need full color, but don’t need transparency, use JPEG instead.

This type is often mistaken for one and only true PNG, and infamously fails in IE6. There are hacks that make it work, but they’re slow and don’t mix well with other CSS properties.

Aside from the IE6 problem, this type creates pretty large files. Avoid it. The silver bullet is below:

If you’ve only ever used Photoshop, you may believe that this type of PNG cannot exist. In reality it’s just Photoshop’s PNG support lacking.

With this type of PNG you get file sizes smaller than GIF, but retain ability to use several levels of transparency.

In paletted PNGs alpha is not a mask, but only an extra component in each palette entry. Thanks to this it gracefully degrades in IE6 — fully opaque pixels are displayed correctly and other pixels are completely transparent. Usually this means that IE6 will drop smooth edges and shadows, but the image will be good enough:

Use this type of PNG whenever you want semi-transparency. You can create these files with (ex-Macromedia) Fireworks. If you’re stuck with Photoshop, you can convert 24-bit PNGs to 8-bit.

There’s a combination of transparencies that doesn’t work even in IE8. If you apply filter:alpha(opacity=α) to an image that is transparent already, IE7-8 will revert to 1-bit transparency and apply alpha channel as a black mask.

If possible, instead of relying on CSS, just create an image that is bit more transparent itself. If you’re only using opacity for fade-in/fade-out, you can probably ignore this problem. If you need a workaround, it’s the same as for IE6.

How red is #FF0000? Answer to this nearly-philosophical question depends on the monitor you have, its settings, and even lighting conditions around you.

But what if you wanted colors in PNG to exactly match the color of your shoes? Color profiles are supposed to solve this oh-so-important problem.

In practice they’re not useful on the Web (even when they work right, and they rarely do.)

If anyone asks, images for the Web are expected to be in the sRGB color space with gamma 2.2.

Don’t enable color management in your software, don’t embed ICC profiles when saving for the Web, and use a PNG optimizer to get rid of any profiles that were embedded.

Color intensity goes from 0 to 255. What’s the value of color that looks half as bright as 255? When PNG was young, different systems agreed only on one thing: it was not between 127 and 128.

I’m serious. For monitors half of 255 is not 127.5. It’s 186! (or 173 if you have a previous version of Mac OS X.)

186 looks as bright as pattern of 0 and 255 pixels
If the color 186 doesn’t look almost like the 0/255 pattern, your monitor is miscalibrated or your browser’s scaling algorithm is buggy.

That crazy thing is called gamma correction and the formula for it is:

(color_sane_person_expects ÷ 255)1gamma × 255 = color_that’s_actually_used

It’s not a PNG quirk. The problem dates back to CRT monitors which didn’t display brightness evenly — applying ¾ of maximum voltage gave only ½ of maximum brightness. Some operating systems tried to compensate for this effect, others didn’t.

PNG had good intentions to fix this mess by encoding gamma value of system/monitor that was used to create the image, allowing other systems to adjust brightness accordigly.

This caused a silly problem: most browsers correct colors in PNGs, but nothing else. All colors in GIFs, JPEGs and CSS may be “incorrect”.

To get colors in PNG exactly as “incorrect” as all other colors in the system, you have to remove gamma information from the files, which prevents browsers from making PNGs holier than the pope.

PNG tools


Typical PNG-saving programs trade compression efficiency for speed and don’t refrain from embedding useless or even problematic metadata in the files.

PNG optimizers fix this. PNGOUT removes all junk and gives the best compression. You can also use OptiPNG + Pngcrush combo. They’re commandline tools. If you’d like to optimize images on a Linux server, this is a useful snippet:

find . -name '*.png' -print0 | xargs -P4 -0 -n1 pngout
                                       ↑ number of CPUs

For the mouse-loving people I wrote ImageOptim. It combines all the best image opti­misa­tion tools with drag’n'drop Mac GUI. Trimage is ImageOptim’s Linux cousin. Windows users might use PNGOUTWin or PNGGauntlet.

Whichever method you prefer, always optimize PNGs.


Since Photoshop doesn’t have a full support for PNG with alpha yet, to get small files and nice transparency, you’ll need pngnq or pngquant. I wrote a simple GUI for it: ImageAlpha.

pngnq uses a very cool algorithm based on neural networks. Side-effect of this is that results are a bit random. Sometimes an image with less colors looks better than an image with more colors (try 255, 254, 253 colors, and so on.)


Problem Solution
File is huge Use 256-color PNG instead of 24-bit (remember: 256-color type also supports full alpha channel)
File is larger than GIF Use a PNG optimizer
Colors in PNG have diff­erent bright­ness than same colors in CSS or HTML Remove gamma information. PNG optimizers usually do it, e.g.,
pngcrush -rem alla input.png output.png
Colors in PNG are still odd Make sure you use the sRGB color space (experiment with the Convert to the sRGB option in Photoshop when saving for Web)
Image has solid gray background in IE6 Use PNG8+alpha instead of 24-bit
Image is invisible in IE6 Make sure the image has some fully-opaque pixels. Use improved pngquant that supports the -iebug flag
Photoshop displays transparency wrong You’ve got PNG8 with alpha not supported by Photoshop. For editing, keep PNG in 24-bit, and convert to PNG8+alpha only when done. You can convert PNG8 to 24-bit by resaving it in, Fireworks or with:
pngout -s1 -c6 -force file.png


You don’t have to read such a long article to use PNG properly. Quick version:

  • PNG works since IE4. If you’re still using GIF, you’re wasting bandwidth.
  • Use 256-color PNGs.
  • Avoid 24-bit PNGs. Use pngquant if you want to have a cake and eat it too.
  • Use a PNG optimizer. You’ll get smaller files and avoid some pitfalls.