My version of the jQuery PNG fix

Published by on Tue, 10/26/2010 - 01:29

Let me first say that I hate IE 6 with a passion. I'm fairly certain that it started as some sort of sick joke and it just spiralled out of control from there.

At any rate, I've been spending (more) time fixing IE 6 bugs in our current site redesign. Some layout issues here and there, some CSS transparency, and of course, transparent 24-bit PNGs. We're using a bunch of those this time around. We've always had at least a couple, but it generally wasn't worth running a JavaScript to fix them, since there were only a couple. So I would just hard code our fix of choice, the AlphaImageLoader.

For instance, the logo HTML would be something like this:

<div id="logo">
    <a href="/">
        <img id="logo-img" src="blank.gif" alt="" />
    </a>
</div>

The CSS for non-IE 6 browsers would be something like this:

#logo, #logo-img {
    width: 100px;
    height: 50px;
}
#logo {
    background: transparent url('logo.png') no-repeat 0 5px;
}

The IE 6 CSS would be:

#logo {
    background-image: none;
    filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=image src='logo.png');
}

This works great for a couple of images, but when you have a bunch, it's not really sustainable. So I went in search of a good JavaScript solution. We use Drupal as our CMS, which has jQuery by default, so I figured a jQuery-based solution would be most efficient.

After a bit of searching around, everyone seemed to point to this one by Andreas Eberhard. But as pointed out by people on various forums and Q&A sites, it had some limitations. It has issues with hidden images in that if the image itself is hidden, it will be shown as a result of the process, and if the image's container is hidden, the height and width will show up as 0px. One of the posts on the StackOverflow link above has a fix for the hidden images showing, but I didn't find it to work very well.

The other problem is that it just hides the images that it is replacing, so if you happen to be using jQuery to show your hidden images at some point, you'll have the processed and non-processed version showing.

So I hacked around with it a bit and came up with some fixes that seem to work pretty well for me. It now hides the unprocessed images and then removes them. It also sets the height and width based on the CSS values if they can't be calculated. Finally, it detects the current 'display:' CSS value and preserves it if it's anything but inline. If it's inline, it still sets it to inline-block like the original script, but anything else will get set to it's original value. So things hidden with 'display: none' will continue to be hidden, and things explicitly set to 'display: block' will still lay out correctly.

I also added the lines to invoke the fix at the end of the file, so you can just include the script on your page after jQuery, and you're good to go. If you want to invoke conditionally, just take out the last 3 lines of code and invoke it wherever you need to.

There are still a couple of limitations. For one, I'm not taking into account other methods of hiding, just 'display: none'. It could probably be adapted to do so, but since jQuery uses 'display: none' for all of its hiding anyway, it should work in most cases. The other issue is that background images that get processed will be scaled to fit whatever they are the background of. So you have to make sure that the size is set explicitly to make sure it doesn't get stretched out of shape.

Well, enough explanation, here's the file. Let me know if there are any more issues with it. It works great for my needs, but I'm sure there's room for improvement.

Download Here