Thursday, September 22, 2011

Backwards compatibility of PNG


If you design website templates, the possibility to use transparent images is very useful. In particular, relying on PNG images is somewhat awesome, because it can contain an alpha (transparency) channel, which tells the renderer how much every single pixel must be transparent. This allows, unlike GIF, to create smooth blendings of the images, no matter what the background color/image is.

Unfortunately, this format is not completely supported by every browser (especially by Internet Explorer, prior to version 7), even though the more modern ones are in step with the times. This problem was (is!) so annoying that the W3C Consortium has one page dedicated to inline transparency testing.

Compatibility issues are an important aspect when dealing with websites, most of all if you're running commercial pages.

Several strategies have been proposed to address the alpha channel issue in PNGs. The one I am proposing here is a javascript-based one.

The principle of this technique comes bundled in a filter included in Microsoft Internet Explorer since version 5.5, called AlphaImageLoader. It takes an image and displays it within the boundaries of a pre-existing image in the HTML DOM, giving support for PNG transparency.

The idea is now straightforward: a completely-blank 1px GIF image is displayed, adapted to the desidered size, and then the requested PNG is applied over it. This could be easily done with the following code:



Unfortunately, this is not as fair as we might think. In fact, this code is completely unportable: Chrome, Mozilla or Opera browsers don't implement AlphaImageLoader filter, so under those browsers, we would get just a blank image.

Then, we have to find a workaround to the workaround. This can be done through Microsoft IE's Conditional Comments. In short, what we're going to do, is to produce some javascript code, save it in a .js file, and include it in the html document as follows:

<!--[if gte IE 5.5000]>
<!--[if lte IE 7]>
<script language="JavaScript" src="pngtransp.js"></script>
<![endif]>
<![endif]>

The full source code for pngtransp.js can be found here. Let's now have a closer look at the interesting snippets, starting from the last line:

window.attachEvent("onload", correctPNG);

This is put there just to "arm the code": when the document is fully loaded, the correctPNG starts up automatically.
That function's purpose is to scan for all images in the document, and check whether they are PNGs or not. This is achieved as follows:

for(var i=0; i<document.images.length; i++)
if (imgName.substring(imgName.length-3, imgName.length) == "PNG")

Later on in the code, we retrieve all information about the image, such as its title, alignment, class name and so on.
Then, we generate new code for the image, which is:

var strNewHTML = "<span " + imgID + imgClass + imgTitle;
strNewHTML += " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"; strNewHTML += "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"; strNewHTML += "(src=\'" + img.src + "\', sizingMethod='scale');\""; strNewHTML += onMouseOver + onMouseOut + "></span>";
in which we create a span with all the previously retrieved information, but with the AlphaImageLoader filter specified. This way, when we invoke:

img.outerHTML = strNewHTML;

the current PNG will be correctly displayed. The procedure is repeated for each PNG image in the document.

The rest of the code is just for overriding the commonly used Dreamweaver's functions to swap images on mouse over, and are not of deep interest to this arcticle.

This way of handling PNG will leave the images untouched if we're using a more "modern" browser, but will correct the alpha blending in more primitive ones.
Though, it has some drawbacks:

  1. Doesn't work in IE versions earlier than 5.5, since AlphaImageLoader is not supported. No cure for those versions.
  2. Javascript must be enabled: you can't assume this on all machines!
  3. CSS image background with PNGs is not supported at all!
  4. If you are displayng a huge document, before the onload event triggers, a while could pass, so at the beginning PNGs could be displayed with the unpleasant gray box around!

The only solution to correctly handle PNGs, is to switch definitively to another web browser!

2 comments:

  1. I faced several issues like this one. A code must be portable and a developer has to take into account his audience and the likelihood that most of people still use old releases of available browsers. However I like to use these tools but have you ever tried to switch from IE version X to a lastest one using png transparency (or something else)? It could be a disaster.

    ReplyDelete
  2. What kind of disaster? Do you mean that transparency is supported in an awkward way producing some sort of artifacts?

    ReplyDelete