Z-Index and Local Stacking Contexts

by Hugh
March 27, 2010

z-index is a CSS property that specifies the order of your elements on the z-axis. The higher the z-index value, the closer the element is to the user. Using z-index is handy to make sure elements like modal dialogs show up above everything else on the page.

div#red { z-index: 1; }
div#green { z-index: 2; }
div#blue { z-index: 3; }

<div id="blue"></div>
<div id="green"></div>
<div id="red"></div>

By default, elements are ordered on the z-axis the same way they’re ordered in the DOM. Without z-indices the order would be reversed in the example above: #blue, #green, #red.

The local stacking context

It gets a little more complicated with nested elements. Keeping the same CSS rules as above and adding an #inner-green element:

<div id="blue"></div>
<div id="green"><div id="inner-green" style="z-index: 4"></div></div>
<div id="red"></div>

#inner-green shows above #blue, because its z-index value is greater than #blue’s 3. But what if you want all of #green‘s child elements to show below #blue? This is when stacking contexts become useful.

You can give an element a new “local stacking context” by setting its position to anything but static and setting its z-index. Z-indicies are only relative to each other on their local stacking context.

<div id="blue" style="z-index: 3"></div>
<div id="green" style="position: relative; z-index: 2">
    <div id="inner-green-4" style="z-index: 4"></div>
    <div id="inner-green-99" style="z-index: 99"></div>
<div id="red" style="z-index: 1"></div>

Now, #inner-green-4 and #inner-green-99 both show beneath #blue, even though their z-indices are larger. That’s because #green establishes its own local stacking context for all of its child elements.

Word of caution, how IE implements z-index differently

In other browsers, a stacking context is created only when an element’s position and z-index are set (other than the default values ‘static’ and ‘auto’). But in Internet Explorer, a local stacking context gets created ever time an element’s position is set.

/* Starts a new stacking context in IE, but not in other browsers */
#green { position: relative; }

/* Starts a new stacking context in all browers */
#green { position: relative; z-index: 1; }

Keep that in mind when you’re debugging IE. Even if an element is assigned a z-index of 2^32, it might still show below other elements because it’s in a different stacking context. In that case, you usually just have to find the ancestor that started the stacking context and assign it a z-index.