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).

Published May 07, 2009
Categorized as HTML and CSS
Short URL: https://snook.ca/s/947

Conversation

31 Comments · RSS feed
Dustin Diaz said on May 07, 2009

That's a nasty one.

Nick Burd said on May 07, 2009

Well if nothing else it made for some interesting twitter posts... :D

46Bit said on May 07, 2009

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.

Peter McKenna said on May 07, 2009

I'm seeing it in IE7 alright, but it seems to work fine for me in IE8 (Vista, IE8 Beta 8.0.6001.18241).

Jonathan Snook said on May 07, 2009

@Peter McKenna: Are you running that in VMware or native? In Windows XP, in VMware, I'm still getting the issue.

Lim Chee Aun said on May 07, 2009

I can confirm it's not working fine in IE8 (8.0.6001.18782) on Vista.

Lim Chee Aun said on May 07, 2009

Oops, it's 8.0.6001.18702.

CG said on May 07, 2009

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.

Jason Grant said on May 07, 2009

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.

Peter McKenna said on May 07, 2009

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).

Nate Cavanaugh said on May 07, 2009

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.

Chris Wallace said on May 07, 2009

What happens when you use 'opacity?'

Jonathan Snook said on May 07, 2009

@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.

Steve said on May 07, 2009

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)

Nate Cavanaugh said on May 07, 2009

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...

Noah Stokes said on May 07, 2009

@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.

Jonathan Snook said on May 07, 2009

@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.

Jonathan Snook said on May 07, 2009

@Noah Stokes: further to that, no, neither display:inline nor zoom:1 solved the problem.

CG said on May 07, 2009

		.content 	{ margin-right:200px; }
		.fixed		{ position:fixed;  top:15px; right:15px; bottom:15px; width:150px; overflow:auto; }
		.fixed span {filter: alpha(opacity=100);}
		input   	{ width:100px;}

	<div id="a" class="fixed">
		<span>
		<h3>Positioned container</h3>

			<input name="e1" type="text" value="">

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

			</span>
	</div>

Does that work?

Sebastian Veggiani said on May 07, 2009

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!

Tanny O'Haley said on May 07, 2009

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?

Ryan said on May 07, 2009

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.

Davor said on May 07, 2009

So nasty...

Michael Kozakewich said on May 08, 2009

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.

yann said on May 09, 2009

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);}

Alex Mansfield said on May 14, 2009

Wow, between the blog post and all the comments, I've learned quite a bit. Gotta love Internet Explorer!

NICCAI said on May 14, 2009

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

CapStone said on May 29, 2009

its true..... :)

dondon said on June 16, 2009

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?

j.j. said on June 18, 2009

> 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:

opacity: 0.8;  /* Firefox, Safari(WebKit), Opera */
filter: alpha(opacity=80);      /* IE 4-7 */
-ms-filter: "alpha(opacity=80)"; /* IE 8 */

For dynamic setting you need only two:

element.style.opacity="0.8";
element.style.filter="alpha(opacity=80)";

See also developer.mozilla.org/en/CSS/opacity

Dan Beam said on April 23, 2011

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:


.fixed * {
    filter: inherit;
}

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.


.fixed a { /* I needed anchors */
    filter: inherit;
}

Worked for me.

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.

Want to learn about scaling CSS for large projects?

I'm available for full and half-day workshops on scalable CSS architecture. I can provide on-site training for your team. Interested?
Get in touch.