HOME - ABOUT

Archive for the ‘CSS’ Category

Handling “z-index” Bugs in IE6

Friday, September 21st, 2007

After some thorough research (i.e. a few Google searches), I hadn’t come up with a fully satisfactory explanation of why IE6 mishandled the z-index attribute. So, here’s a concise survival guide if you intend to use this attribute in IE6.

First, let’s revisit the intended properties of z-index:

  • It applies to positioned elements only.
  • Only when a z-index integer value is specified should a new stacking context be generated.
  • A z-index of “auto” should not generate a new stacking context. It should be the same as its parent.
  • An element with no z-index specified has a default value of auto.

Well, of course IE6 violates the CSS specification and starts handing out z-index values willy-nilly, even when it’s not assigned. Let’s see some examples:

#redbox {
border:1px solid black;
background:red;
width:100px;
height:100px;
position:relative;
top:0px;
left:50px;
z-index:1;
}
#bluebox {
border:1px solid black;
color:white;
background:blue;
width:100px;
height:100px;
position:relative;
top:-50px;
left:100px;
z-index:2;
}
This element has a z-index of 1! So, it should be on BOTTOM.
This element has a z-index of 2! So, it should be on TOP.

So far, so good! Of course, there’s not a lot here to screw up, as it’s all pretty explicit. Now, I will blow things up by adding a parent element to #bluebox:

#parent {
position:relative;
}
This element has a z-index of 1! So, it should be on BOTTOM.
This element has a z-index of 2! So, it should be on TOP.

Well, exactly what wasn’t supposed to happen did. According to CSS specs, nothing should have changed here. Instead, IE6 seems to generate a new stacking context for #bluebox based on its parent, despite the fact that the parent doesn’t even have a z-index specified. Well, what happens if we do specify one?

#parent {
position:relative;
z-index:1;
}
This element has a z-index of 1! So, it should be on BOTTOM.
This element has a z-index of 2! So, it should be on TOP.

Oh, so now we’re okay. But, what if the z-index of the parent element is less than that of #redbox? Let’s make #parent’s z-index 2 and #redbox’s 3. According to CSS, this should establish a local stacking context where the stack level is ‘0′.

This element has a z-index of 3! So, it should be on TOP.
This element’s parent has a z-index of 2! So, it should be on BOTTOM.

Phew; it works. I guess that means that if we set the parent z-index to 4, #bluebox will jump to the top again.

This element has a z-index of 3! So, it should be on BOTTOM.
This element’s parent has a z-index of 4! So, it should be on TOP.

From this, we can deduct that IE6’s main fault is the ill-advised assignment of child z-index values when CSS specifically states that parent elements with no z-index value should not influence the stacking contexts of its children.

So, to be safe, make sure to set a z-index for all your positioned containers to avoid this bug. Or, when possible, simply eliminate the positioning of your parent containers:

#parent {
}
This element has a z-index of 1! So, it should be on BOTTOM.
This element’s z-index is 2. It’s parent is not positioned. It should be on TOP.