0

I know stacking order without z-index has been discussed before, and I understand that positioned and non-positioned elements are treated differently in default stacking order.

However, of all the documents I have read, I still feel very confused whenever it says "in order of appearance", or "descendant non-positioned/positioned blocks", or even "tree order" etc.

I am wondering what is the precise meaning of the rules in this document - in particular, the impact of parent-child hierarchy on stacking order. For example, what happens if a positioned parent has a non-positioned child, or a non-positioned child has a positioned parent?

I have created two examples for demonstration, the css rules are the same across them:

The first one

.non-positioned {
  position: static;
  padding: 5px;
}

.positioned {
  position: absolute;
  padding: 5px;
}

.big {
  width: 200px;
  height: 100px;
}

.medium {
  width: 60px;
  height: 60px;
}

.margin-20 {
  margin: 20px;
}

.bg-red {
  background-color: rgba(255, 0, 0, 0.8);
}

.bg-blue {
  background-color: rgba(0, 0, 255, 0.8);
}

.bg-green {
  background-color: rgba(0, 255, 0, 0.8);
}

.bg-yellow {
  background-color: rgba(255, 255, 0, 0.8);
}

.bg-black {
  background-color: rgba(0, 0, 0, 0.8);
}
<div class="positioned big margin-20 bg-red">
  <div class="positioned medium margin-20 bg-black"></div>
  <div class="non-positioned medium bg-green"></div>
</div>
<div class="non-positioned big bg-blue">
  <div class="non-positioned medium bg-yellow"></div>
</div>

Questions I have here are mainly about the green block:

  1. why the non-positioned green block is on top of non-positioned blue and non-positioned yellow block? In what order definition would green block comes after both blue and yellow?
  2. why the non-positioned green block is even on top of the positioned red block?

The second one

.non-positioned {
  position: static;
  padding: 5px;
}

.positioned {
  position: absolute;
  padding: 5px;
}

.big {
  width: 200px;
  height: 100px;
}

.medium {
  width: 60px;
  height: 60px;
}

.margin-20 {
  margin: 20px;
}

.bg-red {
  background-color: rgba(255, 0, 0, 0.8);
}

.bg-blue {
  background-color: rgba(0, 0, 255, 0.8);
}

.bg-green {
  background-color: rgba(0, 255, 0, 0.8);
}

.bg-yellow {
  background-color: rgba(255, 255, 0, 0.8);
}

.bg-black {
  background-color: rgba(0, 0, 0, 0.8);
}
<div class="positioned big margin-20 bg-red">
  <div class="positioned medium margin-20 bg-black"></div>
  <div class="non-positioned medium bg-green"></div>
</div>
<div class="non-positioned big bg-blue">
  <div class="positioned medium bg-yellow"></div>
</div>

My questions here is: why the positioned yellow block is on top of positioned red and black? It seems straightforward when looked in isolation, but when looked together with the 1st fiddle, what confuses me is that the non-positioned blue parent of the yellow block does not seem to have any impact on its stacking order, while in the 1st example, the positioned parent of green block seems to promote the stacking order of the green div to a higher value.


Edit

After going through all the posts (and the links, specs) provided by others, I managed to figure it out with help of the elaboration here

What I feel important is the rule No.8:

All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order. For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one. For those with 'z-index: 0', treat the stacking context generated atomically.

It basically means that positioned parent, even without z-index, effectively creates a stacking context but only for its non-positioned child elements.

To visualize it, the rendering tree is something like: enter image description here

And the tree of the stacking is: enter image description here

dotted rectangles indicate stacking context (effect).

The positioned red div creates a stacking context effect for its non-positioned child green, but its positioned child black still participates in the parent stacking context which is defined by root node html. Black div comes later because the preorder depth-first traversal has to visit red node first. Same for blue and yellow. Blue and yellow comes before others because they are non-positioned.

Basically I am just looking for evidence in the specification that supports the statement: by default (no z-index or explicit stacking context creation involved), child element never goes below its parent. And that holds because:

  • if both parent and child are non-positioned, tree order (preorder depth first) ensures child is on top.
  • if both parent and child are positioned, tree order (preorder depth first) ensures child is on top.
  • if parent is non-positioned but child is positioned, they both participate in some parent stacking context, and no matter what that is positioned element has higher stacking order.
  • if parent is positioned but child is non-positioned, the positioned parent acts as if it creates a stacking context for its non-positioned child, hence child is always top of the parent.
Xinchao
  • 2,929
  • 1
  • 24
  • 39
  • 1. Because its parent, the positioned red, is in a higher layer than its sibling, the non-positioned blue. – Asons Mar 19 '19 at 17:45
  • 2. Because it is its parent, and won't go below it. – Asons Mar 19 '19 at 17:46
  • 3. Because the position yellow's parent is non-positioned, and being that it will be lower than its sibling, the positioned red (and its children), but the positioned yellow will be on top of all being both positioned, combined with being last in the markup. – Asons Mar 19 '19 at 17:50
  • @LGSon Thanks. so are you saying child element by default will never go below its parent? is that the only thing I am missing? (basically I am looking for general rules if there is any) – Xinchao Mar 19 '19 at 17:55
  • Simply put, yes. With `z-index` you can then alter the positioned one's, even push a child below its parent – Asons Mar 19 '19 at 18:03
  • Linked your question to a great SO post. – Asons Mar 19 '19 at 18:12
  • the SO post you linked is actually one of those that made me confused. I find the presence of z-index much easier to grasp, the blurry part is where z-index is never used. If I follow the rules in that post: (Stacking Order section, no z-index), non-positioned elements first in the order they appear in source code, then positioned elements in the order they appear in source code. It leads exactly to my 1st fiddle, question 2. If non-positioned first, green should be below yellow. Seeing green comes higher made me wonder if I understand what is "the order they appear in source code" – Xinchao Mar 19 '19 at 18:29
  • You miss one thing in the linked post, written in the block quote saying _"Groups of elements with a common parent that move forward or backward together in the stacking order make up what is known as a stacking context."_. The stacking order is initially between siblings, then if a non-positioned sibling has a positioned child, it moves upward with other of its parent's positioned siblings, hence you get the effect in your 2nd fiddle. – Asons Mar 19 '19 at 18:35
  • Right, but that to me is not the definition but the effect of stacking context. E.g. sharing a single parent (even if a positioned one) does not make a stacking context (does it? fiddle 2, yellow block); but if some parent establishes a stacking context, all their children will move forward and backward together – Xinchao Mar 19 '19 at 18:40
  • Then in your first sample, question nr 2, the parent is positioned, hence the child follow it, positioned or not. Within that parent then again, the positioned black will go on top of green being positioned, no matter their markup order. – Asons Mar 19 '19 at 18:41
  • Note, a positioned parent will move to another layer in its stacking context, along with its children. To _create_ a new stacking context, you use `z-index`, and with that you control which one goes above and which goes below. Even if the linked post is confusing, it explains it well. Just give it time and you'll figure it out. – Asons Mar 19 '19 at 18:49
  • Linked post also link to what cause/create a new stacking context: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context – Asons Mar 19 '19 at 18:52
  • I have added another duplicate that better describe parent/child relation – Temani Afif Mar 19 '19 at 19:19
  • Thanks guys, do you mind taking a look of my edit and see if it is correct? Did I over-simplify or over-complicate anything? – Xinchao Mar 20 '19 at 06:27

0 Answers0