:: before伪元素堆叠顺序问题 [英] ::before pseudo-element stacking order issue
问题描述
当静态定位时,:: before伪元素堆栈(z-index)在孩子的内容之前,但是在孩子的背景之后。任何人都可以解释为什么或甚至如何发生这种情况,或者这是所有主要浏览器都有的问题。
< style&
div {background-color:yellow; width:400px; }
div :: before {background-color:red; content:div :: before; }
div :: after {background-color:green; content:div :: after; }
div p {background-color:blue;颜色:白色; margin:-15px 0; padding:0; }
< / style>
< div>
< p> Lorem ipsum dolor sit amet,consectetur adipiscing elit。 Aliquam sed tellus sed tellus sodales hendrerit tristique et elit。< / p>
< / div>
http: //jsfiddle.net/funkyscript/ALrgf/
div
包括两个伪元素和 p
元素,参与相同的堆栈上下文(相对于 div
)。这是因为,你注意到,他们三个都是静态定位;换句话说,根本不定位。 (是的,这些元素在流程中沿z轴堆叠;你根本不能使用 z-index
来操纵它们的堆栈级别,因为它们没有定位。)
这是摘要 1 各种部分的绘制顺序,与您的问题相关的粗体重点:
每个框属于一个堆叠上下文。给定堆叠上下文中的每个定位的框具有整数堆栈级别,其是其在z轴上相对于相同堆叠上下文中的其他堆栈级别的位置。具有较大堆栈级别的盒总是在具有较低堆栈级别的盒的前面格式化。框可能具有负堆叠级别。 在堆叠上下文中具有相同堆栈级别的框根据文档树的顺序背靠背堆叠。
在每个堆叠上下文中,以下图层按照从前到后的顺序绘制:
- 形成堆叠上下文的元素的背景和边框。
- 在线,内联级,非定位后代。
- 子级堆栈上下文与堆栈级别0和定位的后代与堆栈级别0。
>
- 子堆栈上下文具有正堆栈级别(最小为正)。
由于 div :: before
在 div
的内容之前插入,并且在它之后插入 div :: after
静态位置,他们自然会遵循这个规则,即使夹在一个块元素(排序考虑了块框和内联框)。
请注意,原因,背景通常先绘制,内容覆盖它们:
-
p
元素作为块级元素,具有第一个绘制的背景(#3)。 -
内联级伪元素然后用它们的背景绘制
p
背景(#5)。在格式化模型中,它们是p
元素的兄弟,所以它们都参与div
而不是p 。
-
div :: before
伪元素(其内容和背景)出现在p
文本后面,因为它在p
在视觉树中。 -
div :: after
伪元素内容和背景)出现在p
文本前面,因为它在视觉树中的p
之后。 p>
如我在评论中所述,如果你使伪元素显示为块, div :: before
的背景将隐藏在 p
元素,但不是文本;相反, div :: before
的文本将位于背景和 p
元素的文本之间。还要注意 div :: after
的背景是在 p
的前面绘制的,是最前面。同样,这与在上述规则的内容之前或之后绘制的背景有关。
< sup> 1 有关更详细的说明,请参阅附录E 规格
When statically positioned, the ::before pseudo-element stacks (z-index) before the child's content, but after the child's background. Can anyone explain why or even how this is happening or if this is an issue that all major browsers have?
<style>
div { background-color:yellow; width:400px; }
div::before { background-color:red; content:"div::before"; }
div::after { background-color:green; content:"div::after"; }
div p { background-color:blue; color:white; margin:-15px 0; padding:0; }
</style>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sed tellus sed tellus sodales hendrerit tristique et elit.</p>
</div>
http://jsfiddle.net/funkyscript/ALrgf/
The contents of the div
, which include the two pseudo-elements and the p
element, participate in the same stacking context (relative to the div
). This is because, as you note, all three of them are statically-positioned; in other words, not positioned at all. (Yes, these elements do stack along the z-axis while in flow; you simply cannot manipulate their stack levels using z-index
because they're not positioned.)
Here's a summary1 of the order in which the various parts are drawn, bold emphases where relevant to your question:
Each box belongs to one stacking context. Each positioned box in a given stacking context has an integer stack level, which is its position on the z-axis relative other stack levels within the same stacking context. Boxes with greater stack levels are always formatted in front of boxes with lower stack levels. Boxes may have negative stack levels. Boxes with the same stack level in a stacking context are stacked back-to-front according to document tree order.
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).
Since div::before
is inserted before the content of the div
, and div::after
is inserted after it, when they display inline in a static position they'll naturally follow this rule, even if sandwiching a block element (the ordering takes both block boxes and inline boxes into account).
Notice that, for obvious reasons, backgrounds are usually painted first, with the content overlaying them:
The
p
element, as a block-level element, has a background that's painted first (#3).The inline-level pseudo-elements are then drawn with their backgrounds over the
p
background (#5). In the formatting model, they are siblings of thep
element, so they all participate in the stacking context of thediv
and not that of thep
.The
div::before
pseudo-element (both its content and background) appears behind thep
text because it comes before thep
in the visual tree.The
div::after
pseudo-element (both its content and background) appears in front of thep
text because it comes after thep
in the visual tree.
As indicated in my comment, if you make the pseudo-elements display as blocks, the background of the div::before
will hide behind that of the p
element, but not the text; instead, the text of the div::before
will be positioned between the background and the text of the p
element. Also notice that the background of the div::after
is painted in front of that of the p
, while the content is painted frontmost. Again, this has to do with backgrounds being painted before, or behind, content in relation to the rules above.
1 A much more detailed description can be found in Appendix E of the spec.
这篇关于:: before伪元素堆叠顺序问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!