The stacking context

« CSS « Understanding CSS z-index

The stacking context

In the previous example, Adding z-index, the rendering order of certain DIVs is influenced by their z-index value. This occurs because these DIVs have special properties which cause them to form a stacking context.

A stacking context is formed, anywhere in the document, by any element which is either

  • the root element (HTML),
  • positioned (absolutely or relatively) with a z-index value other than "auto",
  • elements with an opacity value less than 1. (See the specification for opacity),
  • on mobile WebKit and Chrome 22+, position: fixed always creates a new stacking context, even when z-index is "auto" (See this post)

Within a stacking context, child elements are stacked according to the same rules previously explained. Importantly, the z-index values of its child stacking contexts only have meaning in this parent. Stacking contexts are treated atomically as a single unit in the parent stacking context.

In summary:

  • Positioning and assigning a z-index value to an HTML element creates a stacking context, (as does assigning non-full opacity).
  • Stacking contexts can be contained in other stacking contexts, and together create a hierarchy of stacking contexts.
  • Each stacking context is completly independent from its siblings: only descendant elements are considered when stacking is processed.
  • Each stacking context is self-contained: after the element's contents are stacked, the whole element is considered in the stacking order of the parent stacking context.
Note: The hierarchy of stacking contexts is a subset of the hierarchy of HTML elements, because only certain elements create stacking contexts. We can say that elements that do not create their own stacking contexts are assimilated by the parent stacking context.

The example

Example of stacking rules modified using z-index

In this example every positioned element creates its own stacking context, because of their positioning and z-index values. The hierarchy of stacking contexts is organized as follows:

  • Root
    • DIV #1
    • DIV #2
    • DIV #3
      • DIV #4
      • DIV #5
      • DIV #6

It is important to note that DIV #4, DIV #5 and DIV #6 are children of DIV #3, so stacking of those elements is completely resolved within DIV#3. Once stacking and rendering within DIV #3 is completed, the whole DIV #3 element is passed for stacking in the root element with respect to its sibling's DIV.

Notes:

  • DIV #4 is rendered under DIV #1 because DIV #1's z-index (5) is valid within the stacking context of the root element, while DIV #4's z-index (6) is valid within the stacking context of DIV #3. So, DIV #4 is under DIV #1, because DIV #4 belongs to DIV #3, which has a lower z-index value.
  • For the same reason DIV #2 (z-index 2) is rendered under DIV#5 (z-index 1) because DIV #5 belongs to DIV #3, which has an higher z-index value.
  • DIV #3's z-index is 4, but this value is independent from z-index of DIV #4, DIV #5 and DIV #6, because it belongs to a different stacking context.
  • An easy way to figure out the rendering order of stacked elements along the Z axis is to think of it as a "version number" of sorts, where child elements are minor version numbers underneath their parent's major version numbers. This way we can easily see how an element with a z-index of 1 (DIV #5) is stacked above an element with a z-index of 2 (DIV #2), and how an element with a z-index of 6 (DIV #4) is stacked below an element with a z-index of 5 (DIV #1). In our example (sorted according to the final rendering order):
    • Root
      • DIV #2 - z-index is 2
      • DIV #3 - z-index is 4
        • DIV #5 - z-index is 1, stacked under an element with a z-index of 4, which results in a rendering order of 4.1
        • DIV #6 - z-index is 3, stacked under an element with a z-index of 4, which results in a rendering order of 4.3
        • DIV #4 - z-index is 6, stacked under an element with a z-index of 4, which results in a rendering order of 4.6
      • DIV #1 - z-index is 5

Example Source Code

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>

    <title>Understanding CSS z-index: The Stacking Context: Example Source</title>

    <style type="text/css">
      * {
        margin: 0;
        }
      html {
        padding: 20px;
        font: 12px/20px Arial, sans-serif;
        }
      div {
        opacity: 0.7;
        position: relative;
        }
      h1 {
        font: inherit;
        font-weight: bold;
        }
      #div1, #div2 {
        border: 1px dashed #696;
        padding: 10px;
        background-color: #cfc;
        }
      #div1 {
        z-index: 5;
        margin-bottom: 190px;
        }
      #div2 {
        z-index: 2;
        }
      #div3 {
        z-index: 4;
        opacity: 1;
        position: absolute;
        top: 40px;
        left: 180px;
        width: 330px;
        border: 1px dashed #900;
        background-color: #fdd;
        padding: 40px 20px 20px;
        }
      #div4, #div5 {
        border: 1px dashed #996;
        background-color: #ffc;
        }
      #div4 {
        z-index: 6;
        margin-bottom: 15px;
        padding: 25px 10px 5px;
        }
      #div5 {
        z-index: 1;
        margin-top: 15px;
        padding: 5px 10px;
        }
      #div6 {
        z-index: 3;
        position: absolute;
        top: 20px;
        left: 180px;
        width: 150px;
        height: 125px;
        border: 1px dashed #009;
        padding-top: 125px;
        background-color: #ddf;
        text-align: center;
        }
    </style>

  </head>
  <body>

    <div id="div1">
      <h1>Division Element #1</h1>
      <code>position: relative;<br/>
      z-index: 5;</code>
    </div>

    <div id="div2">
      <h1>Division Element #2</h1>
      <code>position: relative;<br/>
      z-index: 2;</code>
    </div>

    <div id="div3">

      <div id="div4">
        <h1>Division Element #4</h1>
        <code>position: relative;<br/>
        z-index: 6;</code>
      </div>

      <h1>Division Element #3</h1>
      <code>position: absolute;<br/>
      z-index: 4;</code>

      <div id="div5">
        <h1>Division Element #5</h1>
        <code>position: relative;<br/>
        z-index: 1;</code>
      </div>
   
      <div id="div6">
        <h1>Division Element #6</h1>
        <code>position: absolute;<br/>
        z-index: 3;</code>
      </div>

    </div>

  </body>
</html>

Division Element #1

position: relative;
z-index: 5;

Division Element #2

position: relative;
z-index: 2;

Division Element #3

position: absolute;
z-index: 4;

Division Element #4

position: relative;
z-index: 6;

Division Element #5

position: relative;
z-index: 1;

Division Element #6

position: absolute;
z-index: 3;

See also

Original Document Information

Attachments

File Size Date Attached by
understanding_zindex_04.png
6910 bytes 2005-07-16 18:16:21 Lombardp
XUL_REF_rgb2.png
23532 bytes 2008-05-19 18:26:33 ericjung