Medryx Observations

August 15, 2008

Transparent PNG’s on IE with dojo

Filed under: dojo, javascript — Tags: , , , — maulin @ 5:55 am

Transparent PNG’s are fabulous. They are the key to making your app look really professional and slick. And they allow you to make easily themed web pages without having to redesign all your images, since you can just rely on the background colors shining through the transparency. Transparent PNG support is available on Firefox and Safari, and IE7. But IE6 does not support it.

There are, however, workarounds. And when it comes to making all browsers behave the same in the background, equalizing browser differences so you can just focus on writing great web applications — dojo is the best tool around. So it seems only natural to me that we should try to create a solution to this problem with dojo.

Fortunately, there has already been great work done by Angus Turnbull (which by the way is a GREAT name!) He has created a nifty solution to the problem. It turns out that IE6 does support transparent PNG’s when a special “filter” is used to load the image. Well angus has created a script that uses IE6’s “behaviors” via *.htc javascript files to implement a simple solution that will replace all your images with this filter-loaded version. This includes css background images and IMG tag images. And in his latest version he handles background-repeat and background-position, so this really becomes a simple drop-in solution, and your transparent PNG’s suddenly work perfectly on all the major browsers.

There is just a *little* configration needed to get Angus’s IEPNGFix to work. First you drop the iepngfix.htc, iepngfix_tilebg.js, and blank.gif files somewhere on your server. You then add the following to your CSS file:

img, div { behavior: url(/path/to/iepngfix.htc) }

You also need to open and change the path to blank.gif in iepngfix.htc to the absolute path to the blank.gif file. (Or a relative path, but relative to *any* page that will actually use the file, which is inconvenient). Finally you use a typical script tag to include iepngfix_tilebg.js in your page if you want background-repeat and background-position to work.

Its really not too bad, but its still more work that I want to do. And I would love to be able to use it any dojo web app without all this configuration. Well, dojo to the rescue! With a few modifications, you can make this available with a simple:

dojo.require("medryx.util.png");

(Or you can use whatever namespace you want!) Ideally, this could some day be included in dojo natively, so you wouldn’t have to do any work to get this support. In this technique, you don’t worry about absolute or relative paths — because you replace all that stuff with calls to dojo.moduleUrl
and you can eliminate the change to your CSS with a nifty CSS trick that Angus provides. Finally, you can eliminate the script tag to load iepngfix_tilebg.js by just adding a dojo.provide() call at the top of that file and using a dojo.require() to get it.

Sounds like a lot of work, but really it wasn’t, and now I can use it in any of my web applications without any real work. So here is the step-by-step process:

  1. download the IEPNGFix.zip file
  2. create the following directory structure and copy the files from the zip as follows — lets assume you will put this in a “medryx” module, though obviously yours would be named differently:
    dojotoolkit/
    -- dojo/
    --dojox/
    --dijit/
    --medryx/
    ----util/
    ------png.js --> see below
    ------png/
    --------iepngfix.htc
    --------iepngfix.php --> optional, see below
    --------iepngfix_tilebg.js
    --------blank.gif
  3. Create a file called “png.js” whose contents are quite simple. It simply checks your browser, and if needed, adds a rule to your first stylesheet to handle png’s with the behavior fix (this is a slight modification right from Angus’s demo page). The content of the file is as follows:

    dojo.provide("medryx.util.png");
     
    (function() {
    //a fix for transparent png in ie6 (only works with php, or change this to the iepngfix.htc file if you can get the server to set content-type correctly!
     
    if (dojo.isIE && dojo.isIE < 7 &&  document.styleSheets && document.styleSheets[0] && document.styleSheets[0].addRule){
    	//dojo.require("medryx.util.png.iepngfix_tilebg"); needed to support repeat, but doesn't work for me.
    	var fixUrl = dojo.moduleUrl("medryx.util.png", "iepngfix.php"); //use *.php if your server doesn't server the *.htc file correctly
    	document.styleSheets[0].addRule('*', 'behavior: url("' + fixUrl.path + '")');
    }
     
    })();

    One small thing to notice — the iepngfix.php file is really only needed to set the content-type header of the *.htc file correctly so IE6 will know what to do with it. Obviously there are other (better) ways of doing this on each type of server. But the php file is a simple workaround if you don’t have access to changing how *.htc content-type is set on your server.

  4. Open the iepngfix.htc file and search for “blank.gif”. Replace that line with:

    IEPNGFix.blankImg = dojo.moduleUrl("medryx.util.png", 'blank.gif').path;

    You might also want to search for “alert” and change it to console.warn instead, but that’s not mandatory!

  5. Open the iepngfix_tilebg.js file and add the following to the top line:

    dojo.provide("medryx.util.png.iepngfix_tilebg");
  6. Now on any app that you want to use transparent PNG, just add to your set of dojo.require statements:

    dojo.require("medryx.util.png");

A couple more side notes — I can’t seem to get background-repeat or background-position to work right with the *.js file. I haven’t had time to really troubleshoot it, since I don’t need it right now. If anyone has the solution, please let me know! A second note is that you should consider NOT using 1px images that are repeated, but instead use a more reasonable size, to limit the number of repeats. So if you know the smallest size of your display is 100px wide, then make your PNG 100px wide, and then repeat. Each repeat takes browser processing, and these days the download size of a 1px image and 100px image is not significant enough to make much of a difference.

Hope this helps someone! It has certainly helped me. Thanks Angus!

Powered by WordPress