9

I'm trying to grasp why the blue divs in this example are not always on top? i.e. how come red div #2 is on top of blue child 1.

body {
  padding: 30px;
}
.red1 {
  position: absolute;
  z-index: 1;
  width: 400px;
  height: 200px;
  background: red;
}
.red2 {
  position: absolute;
  z-index: 1;
  width: 400px;
  height: 200px;
  top: 250px;
  background: red;
}
.blue {
  z-index: 9;
  padding: 10px;
  text-align: center;
  color: white;
  text-transform: uppercase;
  position: absolute;
  top: 100px;
  left: 100px;
  width: 150px;
  height: 130px;
  background: blue;
}
<div class="red1">
  <div class="blue">
    blue child 1
  </div>
</div>
<div class="red2">
  <div class="blue">
    blue child 2
  </div>
</div>

FIDDLE

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
Kirk Ross
  • 6,413
  • 13
  • 61
  • 104
  • I am expecting the blue child in the first red div to be on top of red div 2. Both blue divs have a z-index of 9 and both reds have z-index of 1 so how can a red ever be on top of a blue? – Kirk Ross Jul 26 '16 at 17:28

4 Answers4

6

Because .red1 and .red2 form different stacking contexts.

The elements within one stacking context do not participate along with the elements within another stacking context.

If you give .red2 a z-index: -1, you will get the behavior you expect (demo).

That's because .red1 and .red2 are both absolutely positioned with no positioned ancestor. This means the root element is their immediate ancestor, and the root element forms a stacking context.

More details here:

Community
  • 1
  • 1
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • 1
    I would add that if you remove z-index from both red divs you will also get the needed result (the answer of the OP was removed so may we can add it here) – Temani Afif Aug 02 '22 at 22:57
1

Stacking contexts — whether local or root — follow a set of rules that determine the stacking and painting order of elements. Children of a stacking context are painted from bottom to top in the following order. if you flip the order you will see the change. meaning div.red2 then div.red1

0

body {
  padding: 30px;
}
.red1 {
  position: absolute;
  z-index: 1;
  width: 400px;
  height: 200px;
  background: red;
}
.red2 {
  position: absolute;
  z-index: 1;
  width: 400px;
  height: 200px;
  top: 250px;
  background: red;
}
.blue {
  z-index: 9;
  padding: 10px;
  text-align: center;
  color: white;
  text-transform: uppercase;
  position: absolute;
  top: 100px;
  left: 100px;
  width: 150px;
  height: 130px;
  background: blue;
}
<div class="red2">
  <div class="blue">
    blue child 2
  </div>
</div>
<div class="red1">
  <div class="blue">
    blue child 1
  </div>
</div>
  • 2
    Welcome to StackOverflow! Can you please add more details to your answer? It will make easier for people to understand it. – Marina Aguilar Nov 09 '19 at 03:24
0

I propose the following solution, if I understood the stacking order correctly

body {
  padding: 30px;
}
.red1 {
  text-align: left;
  color: white;
  position: absolute;
  z-index: 2;
  width: 400px;
  height: 200px;
  background: red;
}
.red2 {
  text-align: left;
  color: white;
  position: absolute;
  z-index: 1;
  width: 400px;
  height: 200px;
  top: 250px;
  background: red;
}
.blue {
/*
regardless of z-index values
*/
  z-index: auto;
  z-index: -5;
  z-index: 56654;
  padding: 10px;
  text-align: center;
  color: white;
  text-transform: uppercase;
  position: absolute;
  top: 100px;
  left: 100px;
  width: 150px;
  height: 130px;
  background: blue;
}
<div class="red1">RED1 <!-- stacking order = B -->
  <div class="blue"> <!-- stacking order = B.b -->
    blue child 1
  </div>
</div>
<div class="red2">RED2 <!-- stacking order = A -->
  <div class="blue"> <!-- stacking order = A.a  -->
    blue child 2
  </div>
</div>

The display will be in the following order (stacking order):
A (RED2)
A.a (BLUE CHILD 2)
B (RED1)
B.b (BLUE CHILD 1)

oceanGermanique
  • 336
  • 3
  • 16