Why is a textnode rendered below its parents` ::before by default?

﹥>﹥吖頭↗ 提交于 2019-12-11 03:55:22

问题


On writing-up an answer for a different question on SO, I made this snippet:

@import url('https://fonts.googleapis.com/css?family=Shadows+Into+Light');

/* relevant CSS */
div {
  position: relative;
}

div::before {
  content: '';
  position: absolute;
  top: 0; left:0;
}
div>span {
  position:relative;
  z-index:0;
}

/* rest is just styling - should be irrelevant for the question */


div {
  font: normal normal normal 2rem/1 'Shadows Into Light', cursive;
  color: white;
  text-align:center;
  margin: 1rem;
  padding: 1rem;
  min-width: 15rem;
  cursor: pointer;
}
div::before {
  width: 100%;
  height: 100%;
  opacity: 1;
  transition: opacity .3s cubic-bezier(.4,0,.2,1);
  background-color: #bada55;
  border-radius: .4rem;
}
div[orange]:before {
  background-color: #f50;
}
div:hover::before {
  opacity:.65;
}

body {
  margin: 0; padding: 0;
}
center-me-please {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: transparent url(http://lorempixel.com/g/1200/800/fashion) no-repeat 50% 50% /cover;
}
<center-me-please>
  
  <div><span>#bada55</span></div>
  <div orange>not so #bada55</div>

I was surprised to notice the ::before element is rendered above textnodes (orange element) and, in order to prevent it from happening. I had to wrap the textnode in a span element and give it a non-negative z-index and a non-static position (#bada55 element).

On inspection, while the ::before element has a default (expected) value of z-index (auto), the textnode doesn't seem to have one at all (or at least Chrome's not able to show it).

Up to now I liked to think of myself as a z-index little ninja, idea partly backed-up by developing this toy to help friends and colleagues better understand stacking contexts principle and z-index in general.

As you might have guessed, I'm looking for any explanation on why ::before is not rendered below everything else in an element by default (it's first, therefore below, right?) and for any evidence about this being either a (known?) bug or intended (by design?) behavior.

A spec I might have missed or misinterpreted would be great.


回答1:


::before is painted below text content by default — and the default case is when everything is non-positioned.

But your ::before is absolutely positioned. Positioned boxes are always painted in front of non-positioned boxes. Refer to section 9.9.1 (emphases mine):

Within each stacking context, the following layers are painted in back-to-front order:

  1. the background and borders of the element forming the stacking context.
  2. the child stacking contexts with negative stack levels (most negative first).
  3. the in-flow, non-inline-level, non-positioned descendants.
  4. the non-positioned floats.
  5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
  6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
  7. the child stacking contexts with positive stack levels (least positive first).

Wrapping your text content in a positioned span causes it to be painted in front of the ::before content as expected since then you have two positioned boxes in source order.



来源:https://stackoverflow.com/questions/42171688/why-is-a-textnode-rendered-below-its-parents-before-by-default

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!