Friday, April 08, 2005

IE6 opacity filter caveat

This one was a real pain. I was lucky to guess the solution.

I was working on a very small function to set alpha transparency on elements. This is what I came up with:


var ie = (document.all) ? 1 : 0;
var p = (ie) ? "filter" : "MozOpacity";

/* n is the element node
   v is the opacity value, from 0 to 100. */

function op(n,v){
    v = (ie) ? "alpha(opacity="+v+")" : v/100;
    n.style[p] = v;
}

(Yes, I know I left Opera and Safari/KHTML out of the equation.)

This function worked great in Firefox but nothing was happening in IE6. I tried a bunch of different tweaks, none of which worked. Adding an alert(n.style.filter); at the tail end of the function returned "alpha(opacity=50)" indicating that the value was being set correctly for IE6. But the element still rendered at 100% opacity.

Finally, I threw the function out altogether and applied the filter directly to the DIV element via CSS:

<div id="myDiv" style="filter:alpha(opacity=50);">
<img src="MyImage.gif" alt="Some Image Here" 
  width="50" height="50" />
<br />
This should be transparent.
</div>

But it still didn't work! IE6 stubbornly ignored the opacity rule. Even more confusing was that moving the opacity rule to the image alone did work. But only on the image, of course.

<div id="myDiv">
<img style="filter:alpha(opacity=50);" src="MyImage.gif" 
  alt="Some Image Here" width="50" height="50" />
<br />
This should be transparent.
</div>

I really needed the opacity applied to both the text and image. I was about to give up when it occurred to me that maybe the image width and height dimensions has something to do with it. By default, a block element takes on the width of its containing element and height of its content, but maybe IE6 was ignoring this when applying the alpha filter. So I tried this:

<div id="myDiv" 
  style="filter:alpha(opacity=50);
     width:100%; height:100%;">
<img src="MyImage.gif" alt="Some Image Here" 
  width="50" height="50" />
<br />
This should be transparent.
</div>

Yes! Opacity was now being applied to both the image and the text. I removed opacity rule from the DIV and was then able to correctly set opacity via the JavaScript function.

I don't have the luxury of testing this across the different flavors of IE, but it appears that alpha opacity in IE6 requires certain elements to have a specified width and height. What's funny is that when I tried Googling for answers to my problem, I found a ton of working examples that used opacity in IE6 successfully. Looking back now, all of those examples specified a CSS width and height on the element, but didn't make any specific mention of it as a requirement for IE. Removing the width and height caused those examples to fail, too.

UPDATE: Dean Edwards points us to the MSDN documentation for this little-known behavior. IE filters only apply to elements with "layout."

23 Comments:

At 12:28 PM, Anonymous Anonymous said...

Odd. Did you know that in IE 5.0, you can't retrieve the opacity via `currentStyle`? You need to use `style`. Also, if you fade an element (in IE 5.5 or 6, I'm not sure anymore, it's been a while) and you have an iframe in that page, the scrollbars of that iframe will flicker.

 
At 12:38 PM, Anonymous Anonymous said...

Filters only apply to elements with "layout":

http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/haslayout.asp

An obscure Microsoft concept to differentiate between it's different rendering models. Annoying isn't it?

 
At 9:46 PM, Anonymous Anonymous said...

I know you know you left Safari out, but, you should use style.opacity rather than style.MozOpacity. It's the standard css3 property, and works in both Mozilla and Safari.

 
At 11:54 PM, Blogger scottandrew said...

Thanks Tim, I didn't know Moz supported "opacity" (does that mean we can ditch "KhtmlOpacity" too?)

 
At 8:23 AM, Anonymous Anonymous said...

Yup, I got bitten by this one too.

Check out my article: CSS Transparency for Internet Explorer (IE), Mozilla and Safari Redux

I *think* you can just get away with specifying the width. It seems to work for me in my examples.

 
At 3:11 AM, Blogger Martijn said...

Scott, you still have an error in your saveCookie function. It's biting me every time I borrow that code.
var d = new Date();
d.setTime(d.getTime()+(days*24*60*60*1000));
var ex = "; expires="+date.toGMTString();

Error: date is not defined

 
At 12:32 PM, Anonymous Anonymous said...

Out of curiosity, why don't you use more descriptive (e.g. self-documenting) variable names?

var is_ie = typeof(document.all) != 'undefined';
var opacity = (is_ie) ? "filter" : "opacity";

function changeOpacity(node, percent){
percent = (is_ie) ? "alpha(opacity=" + percent + ")" : percent/100;
node.style[opacity] = percent;
}


... requires no explanatory comments, see? (Though it's rather clearer when the lines aren't forced to wrap like that...)

 
At 11:47 AM, Blogger scottandrew said...

Ben: because a lot of my work requires delivering the desired functionality in as little code as possible. This JS usually ends up being compressed, making it even more obscure.

That's why :)

 
At 8:41 PM, Blogger John said...

Mmm, nice. I was just doing a fade out that works for IE and left the job of fixing it to work in Firefox to tomorrow. You just saved me some effort. Thanks!

 
At 4:20 AM, Blogger Faisal ... said...

Thanks for the tip it really worked.

 
At 2:54 PM, Blogger Lucian said...

grate stuff ... it's 00:52 in the AM and IE was driving me nuts ... :) ... I came across your article by mistake (I was searching for something else) ... again many thanks

 
At 2:55 PM, Blogger Lucian said...

works fabu', now I can go to sleep, yeeey :D

 
At 2:22 PM, Blogger Sarah said...

whenever i try to apply opacity to a div containing text, the text becomes very visibly distorted. any suggestions?!

 
At 10:01 AM, Blogger Unknown said...

I was going through the exact same thing and your trick of defining width/height made it to work. thanks so much for posting!

 
At 12:03 AM, Blogger Unknown said...

GOD HOW I HATE FEEBLE PEASANTS WHO SPAM :)

This is an excellent article , thank you.
Though I dont write with Safari in mind I've picked up on the "style.opacity" and the "layout" tips and shall be using them.

 
At 9:49 AM, Blogger Dunk said...

Wonderful mate! If only it had come before I had managed to pull all my hair out....IE, you've got to love it. NOT!

 
At 8:56 PM, Blogger Ian Yang said...

this is really a life saver! i'm working on my website right now and just can't figure out what has gone wrong with this opacity thing. The odd thing is after I put something like:

filter:alpha(opacity=30);
opacity:0.3;

in my style sheet, both FF and IE6 display the effect I want without any further issue. Thanks a lot for this great post! :D

 
At 9:00 PM, Blogger Unknown said...

Rather than using width:100%;height:100%
just try position:relative;

;-)

 
At 3:00 PM, Blogger Goran said...

I'm trying to have transparent text in IE6 but doesn't work with width:100% and height:100% and also doesn't work with position:relative

 
At 9:49 PM, Blogger meusfilia said...

No biggie but there's a tag missing after the div id=myDiv.

 
At 8:28 AM, Blogger Bovine Spongiform Encephalopathy said...

I would just like to say that your blog post has saved me from an hour or so of banging my head against the wall.

It was driving me mental why I simply could not apply opacity to a blockquote element in IE6.

Took your advice and gave it a non percentage based height (percentage didn't work) and hey presto it works.

 
At 8:43 PM, Anonymous Anonymous said...

I checked my web logs the other day, IE6 is still pretty popular.

Setting any of these will give your element a layout...

http://msdn.microsoft.com/en-us/library/ms533776(VS.85).aspx

display: inline-block
height: any value
float: left or right
position: absolute
width: any value
-ms-writing-mode: tb-rl
zoom: any value

 
At 11:28 AM, Blogger Kevin X Brown said...

Thank you very much for the post - very helpful in resolving a problem I have just encountered with applying a gradient filter in IE8, which had the same issue.

 

Post a Comment

<< Home