为何::before伪元素显示在元素上方?堆叠顺序不符预期
伪元素堆叠顺序疑惑:为什么::before会盖住按钮文字?
我原本以为从z-index堆叠规则来看,::before伪元素应该在元素下方,::after在元素上方。想实现按钮hover时仅背景变暗(前景文字颜色不变),但用了::before伪元素后,它居然显示在按钮文字的前方。我知道加z-index能修复,但之前看到Stack Overflow一条获6赞的评论说:“我认为使用:before更好,无需调整z-index就能获得正确的堆叠顺序”,按道理不用调z-index才对,这是为什么?
示例代码
CSS
.parent { --my-color: red; } button { color: blue; background-color: var(--my-color); padding: 8px 16px; position: relative; } button:hover { background-color: transparent; } button:hover::before { display: block; content: ""; position: absolute; top: 0; left: 0; width: 50%; height: 100%; /* width设50%方便调试查看层级 */ background-color: var(--my-color); filter: brightness(80%); }
HTML
<div class="parent"> <button type="button">CLICK ME</button> </div>
问题根源:定位元素的堆叠优先级
那条评论的结论没错,但它的适用场景和你的代码不一样:
- 无定位的默认情况:如果伪元素没有设置
position:absolute/fixed等脱离文档流的定位,默认堆叠顺序确实是::before → 元素内容 → ::after,这时候::before自然在内容下方,不需要z-index。 - 你的代码场景:你给::before加了
position:absolute,它变成了定位元素。在同一个堆叠上下文中,定位元素的堆叠优先级高于普通流的元素内容(也就是按钮的文字),所以::before就跑到文字前面去了。
解决方法
给::before添加z-index: -1,把它放到按钮内容的下方即可:
button:hover::before { display: block; content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: var(--my-color); filter: brightness(80%); z-index: -1; /* 新增该行,将伪元素置于内容下方 */ }
这样既保留了定位伪元素的灵活性,又不用调整按钮本身的z-index,就能实现hover时仅背景变暗的效果。
内容的提问来源于stack exchange,提问作者run_the_race
相关产品推荐
相关产品推荐

