Sunday, March 25, 2012

IE7 z-index issue

The IE z-index bug is old news by now, but since I struggled so much to understand it as a relative newbie to CSS, I wanted to preserve an explanation for posterity.

This is an illustration of the issue - also available via jsfiddle at http://jsfiddle.net/fhJxd/5/
 <div id="parent1" style="position: relative; width: 400px; height: 100px; background: #fcc">
   <span>red header</span>
   <div id="absoluteChild" style="position: absolute; top: 0px; left: 0px; width: 200px; height: 200px; z-index: 100; background: #cfc">
     <span>On all browsers except IE7, the green box will be on top of the blue box on bottom and cover some of the text</span>
   </div>
 </div>
 <div id="parent2" style="position: relative; width: 400px; height: 200px; background: #ccf">          
    <span>The text in this box is fully visible only on IE7.  Even though the green box has a high z-index, IE7 still paints the blue box on top </span>
 </div>

red header
On all browsers except IE7, the green box will be on top of the blue box on bottom and cover some of the text
The text in this box is fully visible only on IE7. Even though the green box has a high z-index, IE7 still paints the blue box on top

This will look different in IE7 and everything else. (The IE8/IE9 developer toolbar correctly replicate the IE7 behavior.)

What's going on here?

The first step is to understand that CSS z-index is not absolute - it's only relative within a "stacking context". Every positioned element with an explicit z-index value (i.e., not 'auto') creates a new stacking context. The z-index values are used to compare elements within the same stacking context; and stacking contexts are hierarchical, so the z-index of the positioned element that created the stacking context in the first place is compared against other elements in the same parent stacking context, and rendered accordingly with its descendants. So it's actually possible for an element with a z-index of 100 to be behind an element with z-index 1, if both are descendants of different positioned elements.

Once you understand that, it's much easier to understand the IE7 problem. IE7's bug is that it treats the unspecified z-index on parent1 and parent2 the same as z-index:0, so parent1 and parent2 each define a new stacking context inadvertently. The z-index of 100 on absoluteChild doesn't matter - the 100 is only used in comparison relative to other descendants of parent1. Since both parent1 and parent2 have the same z-index value, the DOM order breaks the tie.  Then parent2 plus its descendants will paint on top of parent1 and its descendants.

More recent browsers (IE8+, Chrome, Firefox, etc.) will not create a new stacking context for parent1 and parent2.   In that case, the z-index of 100 on absoluteChild causes it to render on top.

There is another good example here: http://therealcrisp.xs4all.nl/ie7beta/css_zindex.html

Post a Comment