问题复现
// html
<div id="parent">
<div id="son"></div>
</div>
// css
<style>
div {
height: 100px;
}
#parent {
width: 100px;
background-color: black;
position: relative;
}
#son {
width: 150px;
position: relative;
left: 10px;
background-color: green;
z-index: -1;
}
</style>
此时,son div因为设置了z-index: -1,所以出现在parent的下面。但是如果给parent设置z-index: 2的时候,son却出现在了parent的上面。
什么是层叠上下文
我们都知道屏幕展示的页面是二维的,也就是说同一个像素点在某一时刻只能渲染一种颜色。那么当有元素重叠在同一个像素的时候,浏览器应该怎么决定渲染哪个元素呢?层叠上下文就是解决这个问题的。层叠上下文是一种抽象能力,我们可以通过一些css属性来让某些元素拥有层叠上下文,而拥有层叠上下文的元素叫层叠上下文元素。浏览器对这种元素增加了z轴方向的维度,可以将这种元素想象成3D模型,该元素的子元素在z轴方向有了排序的能力。
哪些css属性可以触发层叠上下文
- 根节点(
html
)先天就要高人一等,它先天就是一个层叠上下文元素。 position
属性为relative
或者absolute
,且z-index
为数值的元素。position
属性为fixed
或者sticky
的元素。- 直接父级为flex或者grid盒子,并且当前元素z-index不为auto。
- opacity小于1的元素。
- mix-blend-mode不为normal的元素。
transform
/filter
/backdrop-filter
/perspective
/clip-path
/mask
/mask-image
/mask-border
不为none的元素。
层叠等级
层叠等级定义了在同一个层叠上下文中(可以想象为在同一个3D场景当中),内部的元素在z轴上的顺序。
可能有的人会有疑惑,假设元素的父级并没有层叠上下文,那么该元素怎么在z轴方向排序呢?这种情况下,该元素会在最近的拥有层叠上下文的父级的层叠上下文中进行排序。html作为所有元素的父级,是拥有层叠上下文的。
层叠顺序
层叠顺序是层叠等级的实现,具体描述了各类元素在z轴方向的排序。
回归问题
当parent元素不设置z-index的时候,没有创建层叠上下文,然后son元素会向上寻找拥有层叠上下文属性的父级,也就是html。此时parent和son同处于html的层叠上下文中,根据z-index小于0的元素的等级小于block块级水平的元素,所以son会出现在parent的下方。
当给parent设置z-index的时候。parent元素创建层叠上下文,son元素只能在parent的层叠上下文中排序,而parent作为层叠上下文元素,会出现在最底部包裹子元素,所以son会出现在parent的上方。
总结
1. 层叠等级只在同一个层叠上下文中有效,不同层叠上下文下的层叠等级比较没有意义。
2. 元素的层叠等级会向上寻找最近的有层叠上下文的父级的层叠上下文中做排序。