问题
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:
- the background and borders of the element forming the stacking context.
- the child stacking contexts with negative stack levels (most negative first).
- the in-flow, non-inline-level, non-positioned descendants.
- the non-positioned floats.
- the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
- the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
- 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