PNG tips
February 2nd, 2008PNG file format is great. It allows you to be creative and draw cool icons and graphics for your applications with 24bit color depth and an 8bit alpha channel to map transparency.
However, when used in the design of web pages it can cause you some troubles.
Here’s a short summary of good and bad things about it.
PRO
- color depth: up to 48bit, but you will generally use it at 24bit (16777216 colors)
- quality: PNG uses lossless compression (unlike JPEG)
- alpha channel: 8bit (256 opacity levels, unlike the 2 levels of GIF)
- ausiliary information: gamma correction and other useful data is stored into “chunks” embedded in the file (to make the image display correctly on devices different from the one used to create it)
CON
- internet explorer (versions <7): there is no native support for PNG alpha transparency
- gamma correction chunk: yes, it’s a big pro, but unfortunately browsers don’t interpret it correctly. As a result, if you use PNG images in combination with other formats (GIF, JPEG…) and/or with pure CSS colors (as a background for example), it can be a source of big inconsistencies in color and luminance
The solution
Alpha transparency problem: the easiest solution should be banning IE from every modern computer.
An alternative and less drastic way involves the use of the infamous Microsoft.AlphaImageLoader filter plus some pure CSS tricks or Javascript.
Remember, these tricks work only with Internet Explorer 5.5 or grater.
Case 1: you want to fix PNG transparency on a css-defined image (i.e. a background image defined in your stylesheet)
with a solution that is relatively clean (meaning that your code will validate and won’t cause error in other browsers).
First, hide the background definition to IE in your stylesheet (suppose it is style.css) by declaring it through a child-selector (the “>” operator).
#header {
width: 720px;
height: 135px;
position: relative;
}/*start hack for IE6*/
html > body #header {
background: transparent url(../images/header.png) no-repeat;
}
/*end hack*/
While it is correctly interpretated by other browsers (that pick the element with id=”header” in the body, which is clearly a child of the html document),
Internet Explorer ignores it because child-selector was not supported until IE7.
Then, create another stylesheet (let’s call it IEpngFix.css) and add the following definition:
#header {
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader (src="images/header.png",sizingMethod="crop");
}
This Microsoft proprietary filter would generate an error in other browsers, so the third and last step is to link IepngFix.css only in IE with version <7.
It can be done using IE conditional comments in your HTML header:
<!--[if lt IE 7]>
<link rel="stylesheet" type="text/CSS" href="css/IEpngFix.css"/>
<![endif]-->
Notes:
- This solution avoids the use of Javascript and you have total control on what’s happening.
- If you want to fix an image that is used as a repeated background, instead of the “crop” property you should use sizingMethod=”scale” in the AlphaImageLoader
- This hack has one major drawback when the image you are fixing is used as a background for anchor elements: links won’t work! So spend some time planning your website if you’re interested in IE full accesibility.
- It works for 5.5<IE<7.
Case 2: you want to fix a PNG image declared into your HTML into an <img> tag.
The first solution is to use one of the Javascript PNG fixes that you can find around the web (i.e. here).
The second one, is similar to the css solution explained above in the case of images defined within your stylesheet and requires adding the script part to your IEpngFix.css inside an expression():
* html img,
* html .png{
position:relative;
behavior: expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none",
this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "', sizingMethod='image')",
this.src="images/blank.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''),
this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "', sizingMethod='crop')",
this.runtimeStyle.backgroundImage = "none")),this.pngSet=true)
);
}
Note: you must have a transparent gif (in this example “blank.gif”) in your images directory, since it is used as a replacement of the original image that is going to be filtered. If you don’t want to create that image, you can find it in the zip file downloadable at the bottom of this tutorial.
The above solution (that i have found here) works actually with css background images, too:
you just have to add class=”png” to the elements you want to fix.
The only problem is that repeated backgrounds are not allowed, so in that case you have to do it manually as in Case 1.
Gamma correction problem: as you can see in the image below, in this example the color of the PNG image doesn’t match the gray css background, even if you set them with exactly the same RGB values.

To have cross-browser consistency, the only solution is to discard Gamma information (and it’s funny, because Gamma correction exists right to avoid different behaviour between different devices).
You can do it when saving your PNG files directly from your graphic application (Gimp2 as an example) or using a powerful small program called TweakPNG.
With that, you can edit PNG chunks and decide to discard some of them (it’s the program that suggests what’s safe and what’s not).
Download TweakPNG here
That’s all!
Download the sample code of this short tutorial.






