PNG in Windows IE: Info & Links

Home | The Problem | The Solution | How To Use | More Info

This page contains more information for the curious or those who wish to amend the script for special needs.

Pros & Cons

Pros:

Cons:

[1] The figures commonly quoted for the percentage of users with no JS are usually those supplied by The Counter. However, the variances in their statistics are so large as to suggest their system is rather flawed. They reckoned 13% of users had no JS in December 2003. This had dropped to 4% by January 2004! My real-world experience of many users in many businesses and homes is that very close to zero users turn off JS, but your world view and target audience may of course be different.

Troubleshooting

Most of the feedback I receive indicates that the script works fine "out of the box". However, some issues appear often enough for a pattern to emerge. As I receive feedback, I will post problems and solutions here:

How It Works

I left the code uncommented for the sake of brevity, but the explanation below should suffice should you wish to hack it up or improve it.

If used inline, the code runs after any existing onLoad code has completed. If used as an include file, the DEFER keyword ensures it is run when the DOM has loaded, but before the images are rendered. It converts each PNG image into a span with the PNG's width and height attributes. The IE 5.5+ AlphaImageLoader filter is then applied to fill each new span with the original image. It is this filter which allows PNG transparency to work correctly - see KB 294714 for more details. Alt attributes are converted to titles for mouse hover text. Any existing in-line CSS declarations plus title, ID & class attributes are transferred to the new spans.

Each new span has the declaration display:inline-block added - this enables the fix to work with "Standards mode" IE6 Doctypes. Finally, each replaced PNG is checked to see if it has the (deprecated) align="left" or align="right" attribute. If so, an appropriate CSS float declaration is added in-line in order to replicate the original alignment. Also, if the original image was used within an anchor as a link, then a hand cursor is applied to the new span in order to replicate the original link image cursor.

Variations

I was asked to amend the thing for pages with large numbers of images in order to reduce the initial flash of ugly border sometimes seen before the code does its job. I did not include these ideas in the original method as they break the "copy & paste" model somewhat, but they may nonetheless be of use:

(1) CSS Hide

Use a CSS class to hide your PNGs by setting visibility:hidden, then have the JS reveal them again after the transformation by adding visibility:visible straight after sizingMethod='scale'); so that the whole line looks like:

strNewHTML += "(src=\'" + img.src + "\', sizingMethod='scale'); visibility:visible\"></span>" 

Caveat: if the user has CSS enabled and JS disabled, then the images will remain invisible!

(2) JS code on individual PNGs

This method does no checking for deprecated img align="left" or align="right" attributes. It also breaks the non-invasive JS principal somewhat in that it is specifically called by selected PNG images on load in all JS-supporting browsers. However, while the function is called in all browsers, it only actually does something in IE 5.5 and 6.

var arVersion = navigator.appVersion.split("MSIE")
var version = parseFloat(arVersion[1])

function fixPNG(myImage) 
{
    if ((version >= 5.5) && (version < 7) && (document.body.filters)) 
    {
       var imgID = (myImage.id) ? "id='" + myImage.id + "' " : ""
	   var imgClass = (myImage.className) ? "class='" + myImage.className + "' " : ""
	   var imgTitle = (myImage.title) ? 
		             "title='" + myImage.title  + "' " : "title='" + myImage.alt + "' "
	   var imgStyle = "display:inline-block;" + myImage.style.cssText
	   var strNewHTML = "<span " + imgID + imgClass + imgTitle
                  + " style=\"" + "width:" + myImage.width 
                  + "px; height:" + myImage.height 
                  + "px;" + imgStyle + ";"
                  + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
                  + "(src=\'" + myImage.src + "\', sizingMethod='scale');\"></span>"
	   myImage.outerHTML = strNewHTML	  
    }
}

To implement this only on specific PNGs, add the following to each PNG image you wish to transform:

<img src="xyz.png" alt="foo" width="10" height="20" onload="fixPNG(this)">

NB: You must have height and width attributes specified.

Rollovers

Mouseover tricks are usually used to swap images. The standard PNG fix function will break these, as it converts PNG images into spans. There is a way around this, depending on your requirements. If you need this functionality, check out the mouseover demo page.

Imagemaps & Input Images

Imagemaps and images used as form inputs do not work with the regular pngfix, but there is a special version you can use which requires an additional single pixel image in order to work. If you need this functionality, check out the imagemap & input images page.

Other Solutions

There are many other solutions to this problem - you may wish to check them out to see if they better fit your needs:

Fred Boyle emailed me with a Flash solution. He says you can "simply import the PNG into Flash and use the generated Flash movie using the WMODE parameter set to "transparent". This works wonderfully!" . I am not a user of Flash so cannot comment on this approach but hopefully some may find it helpful.

Credits

This hack was inspired by a Zeldman article by Michael Lovitt, who details the core trickery. I simply built on Michael's ideas. Thanks are also due to Kerry Watson who spurred me on to get more features working and helped with testing. Kerry runs the excellent Webcolours PNG advocacy site.

I'm also very grateful to the following:

<< Previous