Search code examples
htmlcssz-index

CSS z-index and stacking contexts


I am trying to better understand the CSS z-index property and stacking contexts.

As practice, I've built a little HTML demo containing some elements, and I am trying to order them in all kinds of different orders using z-index positioning only.

The basic demo is available below, or in this fiddle.

#d1 { /*z-index: ;*/ position: relative; }
#d2 { /*z-index: ;*/ position: relative; }
#d3 { /*z-index: ;*/ position: relative; }
#d4 { /*z-index: ;*/ position: relative; }

#d1, #d2 {
  width: 500px;
  height: 200px;
}

#d3, #d4 {
  width: 300px;
  height: 150px;
}

#d1 {
  background-color: rgba(100,100,100,.6);
}

#d2 {
  background-color: rgba(0,255,0,.6);
  margin-top: -20px;
  margin-left: 20px;
}

#d3 {
  background-color: rgba(255,0,0,.6);
  margin-top: 70px;
  margin-left: 50px;
}

#d4 {
  background-color: rgba(0,0,255,.6);
  margin-top: -70px;
  margin-left: 150px;
}
<body>
  <div id="d1">#d1
    <div id="d3">#d3</div>
  </div>
  <div id="d2">#d2
    <div id="d4">#d4</div>
  </div>
</body>

Now, is it possible to stack the elements in the above demo in the following order (farthest to closest): #d1, #d4, #d2, #d3 ?

(To clarify, the order in the initial demo is: #d1, #d3, #d2, #d4)


Disclaimer:

Prior to asking this question, I have actually searched and read about z-index and stacking contexts. I am familiar with the general rules and specification of how z-index works, and when stacking contexts are created.

Hence, this is not a general "I do not understand how z-index works" question, and therefore it is not a duplicate of this question.

This question refers to the specific case that I have presented above in as much detail as I could. What I ask for is a very specific answer to that specific question - either "Yes, this can be done like so...", or "No, this can't be achieved, because..."


Solution

  • Now, is it possible to stack the elements in the above demo in the following order (farthest to closest): #d1, #d4, #d2, #d3 ?

    No, it is not possible. The farthest you can go is #d1, #d4, #d2 with the following:

    #d1 { z-index: -1; position: relative; }
    #d2 {  }
    #d3 {  }
    #d4 { z-index: -1; position: relative; }
    

    ... but this results in #d1 creating a stacking context for #d3, which prevents #d3 from ever being painted above #d2 or #d4 because the negative z-index of #d1 causes #d1 itself to be painted below #d4 (as two boxes with the same stack level will be painted in source order, and #d4 comes after #d1) and #d2.