Stacking two images in one single IMG element makes overlay transparency easy.

This article was first published on tjkdesign.com (05-26-2006).

It is Aaron Gustafson's iIR technique that inspired this article.

Let's start with two images:

A tranparent GIF (150px * 150px):
A colorful JPEG of same dimensions:

If we write this markup:

<img style="background:url(the_jpeg.jpg)" src="the_gif.gif" alt="" />

We get this:

Pretty cool, isn't?
As you can see, the technique is very straightforward and does not require any extra elements to work.

PNG transparency

PNG transparency is far superior to GIF transparency; unfortunately, Internet Explorer versions 5 and 6 (Windows) lack PNG support. This is why the PNG below shows no transparency in IE 5/6 Win.

To "fix" this problem, one can use an IE proprietary property: AlphaImageLoader filter.
This is how it looks:

<img style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',src='the_png.png')"  src="the_png.png" alt="" />

Now our image is transparent in IE 6, or should I say our "background image" is transparent in IE 6? Because what the filter does is that it paints an image with alpha transparency in the background. It never did anything to our original image, and that's what we need to "get rid of" to see what the filter did for us.
The magic trick is to use a padding declaration to slide the original image "out of the picture" (pun intended).

<img style="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',src='the_png.png');padding-top:150px" src="the_png.png" alt="" />

At this point, we have achieved transparency in IE 5.5** and 6, but at the same time we've created some unwanted padding in most browsers. So to make sure only IE 5 and 6 see our CSS declarations, we replace the style attribute with a class and hide both fixes in a Conditional Comment.
This is the new markup for the image:

<img class="fixMe" src="the_png.png" alt="" />

And this is the Conditional Comment we plug within the head section of our document:

<!--[if lte IE 6]>
<style type="text/css">
.fixMe {filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',src='the_png.png');padding-top:150px}
</style>
<![endif]-->

** The filter works fine in IE 5.5. If we cannot see any transparency in this browser it is only because the "padding" trick does not work with IE 5. If we were using a transparent image as src value, then we would see the jpeg image through the overlay (unfortunately this other trick would make the latter disappear in modern browsers).
See below for a DOM solution that does work in IE 5.5.

Using the PNG as overlay

It is now as simple as applying a background image to our img element.

<img class="fixMe" style="background:url(the_jpeg.jpg)" alt="An indigen" src="the_png.png" />

Note that I did not leave the alt attribute empty.

Keeping the style inline allows authors to set JPGs dynamically (i.e. in a repeat region); but replacing the style attribute with an ID is all you need to apply the JPGs through the stylesheet.

Bringing the DOM into the picture

A few weeks ago, a client asked me how to apply an overlay to several images to simulate TV screens. Although he was using an extra element (a span) with complex CSS rules, he was running into different browser issues.

With a scripted solution, it is possible to free the img element from the class attribute, batch the whole process and at the same time make the technique IE 5.5 compatible.

See the script below in action

<!--[if lte IE 6]>
<script type="text/javascript">
function TJK_fixOverlay(){// v 1.0 Copyright 2006, Thierry Koblentz - TJKDesign.com. All rights reserved.
    var arrImages = document.getElementsByTagName("img");
    var arrPNGimages = new Array();
    var zImages;
    for(var i=0; i<arrImages.length; i++){
        zImages = arrImages[i];
        if(arrImages[i].src.substring(arrImages[i].src.length-3,arrImages[i].src.length)=="png"){
        arrPNGimages.push(zImages);
        }
    }
    for(var x=0, y=arrImages.length; x<y; x++){
        arrPNGimages[x].style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',s/tv.png')";
        arrPNGimages[x].src="transparent.gif";
    }
}
window.onload=TJK_fixOverlay;
</script>
<![endif]-->

Making sure the markup makes sense

As the previews example shows, this is not the best way to mark up img elements.

PNG overlay with class uses the script below. This script allows authors to use jpeg as src values.

function TJK_SetOverlay(){ // v 1.0 Copyright 2006, Thierry Koblentz - TJKDesign.com. All rights reserved.
    if(!document.getElementsByTagName)return;
    var arrImages = document.getElementsByTagName("img");
    var arrImgToFix = new Array();
    var zImages;
    var classCount = 0;
    for(var i=0; i<arrImages.length; i++){
        if(arrImages[i].className=="overlayMe"){
            arrImgToFix[classCount]=arrImages[i];
            classCount++;
        }
    }
    for(var x = 0, y = arrImages.length; x < y; x++){
        if(arrImgToFix[x]){
            arrImgToFix[x].style.background="url("+arrImgToFix[x].src+")";
            // we go two ways: non IE Win and IE Win
            if (!arrImgToFix.push || !document.all){
                arrImgToFix[x].src="img/new_png.png";
            }else{
                arrImgToFix[x].style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',src='img/new_png.png')";
                arrImgToFix[x].src="img/transparent.gif";
            }
        }
    }
}
window.onload=TJK_SetOverlay;

This last example does not even use the class attribute: Overlay with no hook