的内容div
,包括两个伪元素和p
元素,参与相同的堆叠上下文(相对于div
)。这是因为,正如您所注意到的,它们三个都是静态定位的。换句话说,根本没有定位。(是的,这些元素在流动时确实沿 z 轴堆叠;您根本无法使用它们来操纵它们的堆叠级别,z-index
因为它们没有定位。)
这是绘制各个部分的顺序的摘要1 ,与您的问题相关的粗体强调:
每个盒子属于一个堆叠上下文。给定堆叠上下文中的每个定位框都有一个整数stack level,这是它在 z 轴上相对于同一堆叠上下文中其他堆叠层级的位置。具有较高堆栈级别的框总是在具有较低堆栈级别的框之前格式化。盒子可能有负的堆栈级别。在堆叠上下文中具有相同堆叠级别的框根据文档树顺序从后到前堆叠。
在每个堆叠上下文中,以下图层按从后到前的顺序绘制:
- 构成堆叠上下文的元素的背景和边框。
- 具有负堆栈级别(最负优先)的子堆栈上下文。
- 流入的、非内联级别的、非定位的后代。
- 未定位的浮动。
- 流入的、内联级的、非定位的后代,包括内联表和内联块。
- 堆栈级别 0 的子堆栈上下文和堆栈级别 0 的定位后代。
- 具有正堆栈级别的子堆栈上下文(最不积极的优先)。
由于div::before
在 的内容之前插入div
,并且div::after
在其之后插入,当它们在静态位置显示 inline 时,它们自然会遵循此规则,即使将块元素夹在中间(排序同时考虑块框和内联框) .
请注意,出于显而易见的原因,通常首先绘制背景,然后将内容覆盖在它们之上:
该p
元素作为块级元素,具有首先绘制的背景(#3)。
然后在背景上绘制内联级伪元素p
(#5)。在格式化模型中,它们是p
元素的兄弟,所以它们都参与了 的堆叠上下文,div
而不是. 的堆叠上下文p
。
div::before
伪元素(其内容和背景)出现在文本后面,因为p
它p
在可视树中位于 之前。
div::after
伪元素(包括它的内容和背景)出现在文本的前面,因为p
它p
在可视化树中出现在后面。
正如我的评论中所指出的,如果您将伪元素显示为 blocks,则背景div::before
将隐藏在p
元素的背景后面,而不是文本;相反, 的文本div::before
将位于背景和p
元素文本之间。另请注意, 的背景div::after
绘制在 的前面p
,而内容绘制在最前面。同样,这与在与上述规则相关的内容之前或之后绘制背景有关。
1 更详细的描述可以在规范的附录 E中找到。