0

Originally I wondered why span elements render over 'later in the DOM defined' elements. But by further experimenting I was able to isolate it to "inline elements (and text nodes) rendering over block elements".

Why does that happen? - why do inline elements render over block elements even though they are earlier in the dom (order of appearance)?

This is my experiment, with those spans having fat padding to take up more space.
https://codesandbox.io/s/z-index-stacking-context-ftg68m

/* code originally from https://codepen.io/philipwalton/pen/AeNzWJ */
/* stacking context explaiend here https://philipwalton.com/articles/what-no-one-told-you-about-z-index/ */
/* stacking without z-index here https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_without_z-index */

div {
  border: 10px solid transparent;
  height: 30px;
  width: 100px;
}

div + div {
  margin-top: -20px;
}

.r {
  border-color: orange;
}
.g {
  border-color: lime;
  margin-left: 10px;
}
.b {
  border-color: blueviolet;
  margin-left: 20px;
}

.red,
.green,
.blue {
  color: white;
  padding: 30px;
  margin-left: 20px;
  /* (un)comment position */
  /* position: relative; */
}

.red {
  /* (un)comment z-index */ /* PS: z-index won't take effect until the element is "positioned" (has `position:` other than default static) */
  z-index: 1;
  background: red;
}

.green {
  background: green;
}

.blue {
  /* (un)comment z-index */ /* PS: z-index won't take effect until the element is "positioned" (has `position:` other than default static) */
  z-index: -1;
  background: blue;
}

/* Experiment two */

div.red,
div.green,
div.blue {
  height: 0px;
  width: 0px;
  padding: 25px;
}

div.r div,
div.g div,
div.b div {
  margin-top: -20px;
}

.inlineBlock {
  display: inline-block;
}

.inline {
  display: inline;
}

hr {
  margin-top: 50px;
}
<main id="root">
   Span
   <div class="r"><span class="red">1</span></div>
   <div class="g"><span class="green">2</span></div>
   <div class="b"><span class="blue">3</span></div>
   <hr>
   Div (block)
   <div class="r">
      <div class="red">1</div>
   </div>
   <div class="g">
      <div class="green">2</div>
   </div>
   <div class="b">
      <div class="blue">3</div>
   </div>
   <hr>
   Div (inlineBlock)
   <div class="r">
      <div class="red inlineBlock">1</div>
   </div>
   <div class="g">
      <div class="green inlineBlock">2</div>
   </div>
   <div class="b">
      <div class="blue inlineBlock">3</div>
   </div>
</main>
<div>
  <span>1</span>
</div>
<div>
  <span>2</span>
</div>
<div>
  <span>3</span>
</div>

<hr/>

<div>
  <div>1</div>
</div>
<div>
  <div>2</div>
</div>
<div>
  <div>3</div>
</div>

enter image description here

More reading:
stacking context explaiend here https://philipwalton.com/...about-z-index/
stacking without z-index here https://developer.mozilla.org/.../Stacking_without_z-index

Qwerty
  • 29,062
  • 22
  • 108
  • 136
  • This is the answer that finally made it click! https://stackoverflow.com/questions/48731110/why-the-content-is-not-covered-by-the-background-of-an-overlapping-element/49086004#49086004 The reason is rendering optimizations with GPU to ease CPU! – Qwerty Jun 22 '22 at 13:36

1 Answers1

1

In stacking contexts where no element has been given a z-index, the stacking order is calculated like so (from furthest to closest).

  1. Backgrounds and borders of the root element
  2. Non-positioned, non-floating block elements, in the order they appear in the source code
  3. Non-positioned floating elements, in the order they appear in the source code
  4. Inline elements
  5. Positioned elements, in the order they appear in the source code

As you can see, inline elements will always appear above block elements because, quite simply, that's the way it is.

Here's a great overview with more information:

Understanding z-index stacking order

Geat
  • 1,169
  • 6
  • 17