Fixed Position and Opacity Filter Bug in Internet Explorer
I think I have a knack for discovering weird edge cases but here was a wacky one that had me scratching my head for awhile. In working on some interface development, I wanted to have an element with fixed positioning, locking it to the viewport. In this particular case, it quickly animates in by adjusting the opacity of the element from 0 to 100. Straightforward enough, right?
But in Internet Explorer 7 and 8 (even in standards mode), I wasn't able to scroll and while I could type in my form inputs, nothing was showing up. Resizing the browser forced a redraw and everything looked okay but you still couldn't scroll or see anything you typed into a text field.
Here is the CSS that was causing all the ruckus:
.fixed {
position:fixed;
filter: alpha(opacity=100);
top:15px; right:15px; bottom:15px;
width:150px;
overflow:auto;
}
I've put together a simplified test case that demonstrates this. Check it out in IE7 or 8 and you should see the unfortunate side-effect. Click on the Remove Filter button and the functionality of the fixed area should return to normal.
Putting the test case together for this was a hassle. Because the filter was being applied via script, all my original assumptions weren't working. It was only when I started pasting in rendered HTML from IE (using IE's developer toolbar in IE8) that I was able to recreate the issue (since the rendered HTML had the filter applied).
Conversation
That's a nasty one.
Well if nothing else it made for some interesting twitter posts... :D
Yeah, happens for me as well - def. not a bug just on your system or something of that irk. I'm not aware of anything like this noted anywhere either though - and it's certainly a very strange bug.
I'm seeing it in IE7 alright, but it seems to work fine for me in IE8 (Vista, IE8 Beta 8.0.6001.18241).
@Peter McKenna: Are you running that in VMware or native? In Windows XP, in VMware, I'm still getting the issue.
I can confirm it's not working fine in IE8 (8.0.6001.18782) on Vista.
Oops, it's 8.0.6001.18702.
I have ran into this one once, you really don't want to look at it in IE6. But what you can do is put a span or div inside the fixed div and apply the filter to that. I know it is extra markup, but sometimes you just need it to work.
This kind of problem can be also found when using PNG transparency fixes for IE.
What ends up happening is that the transparent layer, after being 'fixed' creates a top level layer on the site which cannot be clicked through.
If this 'top level layer' covers something like a link, that link can be seen, but not interacted with.
We worked out this unfortunate fact on a very expensive, high-level project which then massively and significantly impacted on the design, which had to be majorly simplified in order to 'fit with the way web works' as I call it.
Overall message: design for what the technology can handle.
I'm running IE8 natively on Windows Vista and it works fine. It breaks once I run IE8 in Compatability View (I know not exactly the same as IE7).
It will work in IE8 if you use the new -ms-filter notation (at least it is for me), but when I use the old filter, it wonks out.
What happens when you use 'opacity?'
@Nate Cavanaugh: well, that's a fascinating twist. You wouldn't think it'd really matter.
@Chris Wallace: IE7 nor 8 support the opacity property. Therefore it'll have no effect.
yeah it is definately messed up in IE7/IE8.
Does it fix itself if/when you use the new and improve IE8 method of applying filter rules?
-ms-filter:...
(see IE Blog for details)
Nevermind, the -ms-filter thing isn't being read at all. Either way, I wish I could say this was surprising, but IE somehow manages to be completely mundane and completely dynamic at the same time in the bugs it has...
@Jonathan - I'm not sure if I missed it or not, but did you come up with a fix?
@Jason Grant - Your overall message of "design for what the technology can handle" is a though provoking topic. Thx for sharing that.
@Noah Stokes: Sort of. In my particular case, because I was animating to 100% opacity, I could just remove the opacity filter once the animation was complete. However, for a situation where you might want a semi-transparent layer that still responds interactively, I do not have a solution. I could try some test cases with my usual hacks: display:inline or zoom:1.
@Noah Stokes: further to that, no, neither display:inline nor zoom:1 solved the problem.
Does that work?
My results:
(VirtualPC VM) Windows XP SP3 w/ IE 8.0.6001.18702 = BUG!
Windows XP SP3 w/ IE 7.0.5730.13 = BUG!
Good luck!
There's also a side effect in IE7 when applying a filter like opacity to an element. IE7 turns off Clear Type when an element has opacity applied to it. To turn Clear Type back on you have to completely remove the filter. I found this problem with several drag and drop libraries where they didn't remove the filter.
When I look at your "simplified test case" using IE7 on an Win XP computer with Clear Type turned on, the main body text is nice and readable, while the text in the positioned container is pixelated and difficult for me to read.
Microsoft blog has an entry, Notes on the interaction of ClearType with DXTransforms in IE7 that addresses the filter and Clear Type issue.
I wrote about this way back in May of 2007 in Has IE7 Broken CSS Filters?
Nice find on that weird behaviour. The cleartype issue can be fixed by applying a background colour to the fixed element e.g. background-color: #fff; forces the text to render with clearType.
As for the scrolling not happening you could possible append the disable property in the filter alpha e.g. filter: alpha(opacity=100, enabled=false); I know it's the same way as just removing the opacity property but you could access it via scripting and enable or disable when needed.
So nasty...
Jason had mentioned that a layer is created over everything. Is it possible to find that layer and change the z-index? Or possibly move it out the way with margins?
It's always annoying when strange rendering modes pop up.
Not an exact fix, but you could add a div inside the fixed div and apply the filter to that one. The scrollbar won't fade in so you could just switch the overflow to auto at the end of the animation, with the appropriate margin adjustment, the div wouldn't jump around and if the anim is fast enough, the scrollbar popin in at the last minute might not be a deal breaker.
something like #fade inner div with:
#fade { zoom: 1; filter: alpha(opacity=50);}
Wow, between the blog post and all the comments, I've learned quite a bit. Gotta love Internet Explorer!
This is similar to the issue where cleartype is lost in IE when filter opacity is used - most often during a fade.
http://blog.niccai.com/post/56904970/losing-cleartype-in-internet-explorer
its true..... :)
It takes 4 CSS opacity style codes to cover browsers old and new if you want cross-browser coverage. I'd really like to use these 4 opacity properties in DHTML so I need to be able to refer to their CSS style properties and make dynamic changes. But even though a couple of them can be found, a couple cannot, and maybe they don't have ways to reference them from Javascript, and we're stuck with simple CSS style scripts. Here's as far as I have been able to take this:
http://www.css-resources.com/The-CSS-Opacity-Property-Pop-up-Method.html
You can see how silly it is to have to do slow fades the hard way in order to make the script work on all browsers. Obviously I could use 1 or 2 DOM CSS style properties dynamically, but not all of them. Any thoughts or insights?
> It takes 4 CSS opacity style codes to cover browsers
No, it doesn't.
-moz-opacity
is dead since June 2004 (Firefox 0.9)-webkit-opacity
is dead since February 2004 (Safari 1.2)You need this three:
For dynamic setting you need only two:
See also developer.mozilla.org/en/CSS/opacity
Hey Jonathan,
I know this post is a little old, but triggering hasLayout with zoom: 1; or overflow: auto; (or min-width: 0;?) didn't work for me on chidren with float: right; positon: relative; display: block; (+ hasLayout before, so kind of inline-block for IE).
Instead I tried this:
to make all the subnodes in the tree inherit that transparency, and it seemed to work.
NOTE: because of the limitations of filters (i.e. setting one destroys another, like shorthand properties destroy long hand, background -> background-color), this would nuke a gradient or something else if not cascaded correctly. You could alternately scale down that universal selector to the nodes you need for the nuking reasons and performance, i.e.
Worked for me.