The web is full of articles discussing how to render transparent 24-bit png images in IE6 – so why write another one?
Three reasons. First, although the long hoped for demise of IE6 is finally showing some progress, IE6 still has a 20% to 40% market share, which is still more than Firefox. Second, none of the existing articles talk about the terrible performance degradations caused by the most common solutions proposed to display png files and how to avoid them. Third, I discovered an alternate solution using VML that I’ve never seen documented.
AlphaImageLoader is Slow
Let’s start with the performance issues. Most websites recommend enabling transparent png’s in IE6 by running javascript code when the page loads. The javascript finds all png images on a page and applies Microsoft’s proprietary AlphaImageLoader filter.
What almost no article mentions (the one I linked to above being an exception) is how badly this degrades page load performance. But don’t take my word for it – I’ve setup an example page that loads sea-level rise data from Peter Black’s excellent climate atlas blog.
At the top of the page are several buttons – click the far left one, titled Slow, to see how the typical png solution performs. Go ahead, try it now (using IE6 of course). Notice how the browser freezes for over 10 seconds and doesn’t display any images until the very end? Not very good, is it?
But if you view the same files using Google maps, the performance is much better. And you can also see each tile as it loads, instead of waiting for the end. So how did Google achieve this sleight of hand? A bit of digging shows the trick – instead of fixing all the images at once, Google fixes them one at a time. This is done by attaching an onload event handler to each image that needs to be fixed. When the image is loaded, the onload event applies the AlphaImageLoader filter. This avoids IE freezing. And to avoid the annoying flashing caused by applying the filter, images start off “hidden” and are only made visible when their onload events are fired. Clever, isn’t it?
Now go back to the example page and click the second button, titled Fast. The difference is amazing – like night and day. As an extra bonus, the onload event for image elements that point to invalid or non-existent images never fires, meaning that they are never made visible. That neat trick avoids IE displaying an annoying red x () for invalid images.
A New Approach – VML
A couple of years ago I discovered an entirely new way of displaying 24-bit transparent png images in IE – use VML. Somehow I’ve never managed to put it down on paper (wrong metaphor I know, but humor me). I figure I’d better do it now before this tidbit of knowledge becomes irrelevant.
It’s little known that VML supports not only vector graphics, but also raster images via its image element. And I’ve never seen it mentioned that the vml:image element supports transparent 24-bit pngs.
To see VML in action, go back to the example page and click the third button, titled VML. The first time you click the button, the performance won’t be very good since all the images are first downloaded. But once the page is loaded, click the Clear button and then click the VML button. From my testing, the performance is noticeably better than using the AlphaImageLoader.
There are several things to note about the VML code that took me hours to figure out:
- The setupVml function enables VML via Javascript – its two lines of code are barely documented on the web and thus took hours of fiddling to get working
- You must set the width and height of the VML images, otherwise nothing is displayed
- You must set the coordsize of the VML images – otherwise they will be randomly one pixel to short or wide
Sadly, the VML solution suffers three problems that make in unsuitable most of the time. First, notice the images are a bit fuzzy when displayed with VML. I haven’t a clue as to why.
Second, images that don’t load are shown with IE’s annoying red x mentioned above. The problem is that VML images don’t seem to support the onload event (or onreadystate), so there is now way to start them off as hidden and then make them visible once the image has loaded.
Third, IE6 doesn’t cache VML images across page loads. To see this, reload the example page and press the VML button again. Notice the long delay? If you watch IE’s http traffic (say using Fiddler), you’ll see that IE6 requests each image again. It does not do that for html image elements, which you can verify by running the same experiment but clicking the Fast button instead.
Together, these three issues make the VML solution inferior to the AlphaImageLoader solution, but I thought I’d write it down in case someone ever needs to know about it.