Search code examples
cssz-index

Why does green div come on top of red div?


https://codepen.io/anon/pen/dBdaWE

In the codepen above I have 2 divs red and blue. Using z-index we make sure red is above blue even if it comes before blue in markup.

green is a child of blue with z-index of 9999. Even though it's z-index is high it should be trapped inside blue which is clearly below red. As said in the CSS tricks article: https://css-tricks.com/almanac/properties/z/z-index/

Also note that nesting plays a big role. If an element B sits on top of element A, a child element of element A can never be higher than element B.

How does green div, which is a child of blue is able to come on top of red div?


Solution

  • !! note, all quotes here below with a * at the end are from this source

    Also note that nesting plays a big role. If an element B sits on top of element A, a child element of element A can never be higher than element B.*

    How does green div, which is a child of blue is able to come on top of red div?

    You have probably mis-interpret that sentence. It is meant for that situation where none of the elements have z-index set. If you style the elements without setting the z-index, it holds the truth. Look at the interactive example here below, which is without modifying the z-index of the elements.

    .main {
      border: 1px solid;
      padding-left: 50px;
    }
    
    .red, .blue {
      width: 100px;
      height: 100px;
    }
    
    .red  {
      background-color: red;
      position: relative;
      top: 50px;
      left: -50px;
    }
    
    .blue {
      background-color: blue;
    }
    
    .green {
      width: 50px;
      height: 50px;
      position: relative;
      top: -25px;
      background-color: green;
    }
    <div class="main">
      <div class="red"></div>
      <div class="blue">
        <div class="green"></div>
      </div>
    </div>

    As you can see, the following statement is true

    Without any z-index value, elements stack in the order that they appear in the DOM (the lowest one down at the same hierarchy level appears on top)*

    However, it is not obvious first because blue's position is static, in contrary to the other two elements, whose position are relative (thus non-static). If you expect that blue is above red (and below green), then you have to change its position CSS attribute. It is also mentioned in the link, as quoted here below

    Elements with non-static positioning will always appear on top of elements with default static positioning.*

    In the example here below, I have given the blue element (look for "ADDED") a non-static position value. This leads to a similar behavior as when all element's position are static: red comes first, then blue comes on top of it, followed by green on top of it because it is a child of blue (lower in hierarchy).

    .main {
      border: 1px solid;
      padding-left: 50px;
    }
    
    .red, .blue {
      width: 100px;
      height: 100px;
    }
    
    .red  {
      background-color: red;
      position: relative;
      top: 50px;
      left: -50px;
    }
    
    .blue {
      background-color: blue;
      position: relative; /* !! ADDED !! */
    }
    
    .green {
      width: 50px;
      height: 50px;
      position: relative;
      top: -25px;
      background-color: green;
    }
    <div class="main">
      <div class="red"></div>
      <div class="blue">
        <div class="green"></div>
      </div>
    </div>

    Now, back at the first quote;

    Also note that nesting plays a big role. If an element B sits on top of element A, a child element of element A can never be higher than element B.*

    This occurs when you are only giving the element B (in this situation, it is .red) a z-index value. In the example here below, I have added a z-index value to the red element.

    .main {
      border: 1px solid;
      padding-left: 50px;
    }
    
    .red, .blue {
      width: 100px;
      height: 100px;
    }
    
    .red  {
      background-color: red;
      position: relative;
      top: 50px;
      left: -50px;
      z-index:1; /* !! ADDED !! */
    }
    
    .blue {
      background-color: blue;
      position: relative;
    }
    
    .green {
      width: 50px;
      height: 50px;
      position: relative;
      top: -25px;
      background-color: green;
    }
    <div class="main">
      <div class="red"></div>
      <div class="blue">
        <div class="green"></div>
      </div>
    </div>

    See, the green element does not appear anymore. This is because red is above blue. And green is a part of the blue.

    In yours question, you have given green another z-index value. This will overrule the current behavior so that it becomes above the red element as shown here below.

    .main {
      border: 1px solid;
      padding-left: 50px;
    }
    
    .red, .blue {
      width: 100px;
      height: 100px;
    }
    
    .red  {
      background-color: red;
      position: relative;
      top: 50px;
      left: -50px;
      z-index:1;
    }
    
    .blue {
      background-color: blue;
      position: relative;
    }
    
    .green {
      width: 50px;
      height: 50px;
      position: relative;
      top: -25px;
      background-color: green;
      z-index: 2; /* !! ADDED !! */
    }
    <div class="main">
      <div class="red"></div>
      <div class="blue">
        <div class="green"></div>
      </div>
    </div>