z-index与堆叠上下文

z-index

说明:以下说到“定位元素”时,均指 position 属性不为 static 的元素。

z-index 属性用于设置一个定位元素及其后代元素在Z轴(垂直屏幕的轴,指向屏幕外的方向为正)上的顺序(或层级)。
当元素与元素之间的位置有重叠时,z-index 较大的元素会覆盖较小的元素。

注意z-index 的比较只在同一个堆叠上下文中有意义,在不同的堆叠上下文内比较 z-index 的大小来判断层级顺序的排布是毫无意义的。

值得一提的是在MDN文档中有提到 z-index 属性还可以设定 flex 项目的 z-order。
但是我尚不理解是什么意思。
使用两个同级的定位元素和flex元素来测试,可是并没有出现更高 z-index 属性的flex元素覆盖更低 z-index 定位元素的情况。

除了几个全局的值 inheritinitialunset 之外,z-index 属性可以设置的值有关键字 auto 和整数。

auto 与 0

在单纯的两个分别设置了 z-index: autoz-index: 0 的定位元素进行比较层级时,二者的表现是一样的。
可以简单的认为 z-index: auto 的层级表现就是 0。

但是既然在这里单独拿出来比较二者有什么不同了,那肯定还是有区别的。
它们的不同之处就在于:

z-index: auto 不会创建新的堆叠上下文,而 z-index: 0 会创建一个新的堆叠上下文。

堆叠上下文

什么是堆叠上下文?

首先我们需要简单了解一下页面中每个元素的绘制情况。

把页面想象成一个桌面(或者别的什么平台的一个平面),每个元素想象成一张薄纸,元素的绘制,就像是把一张张纸按顺序从顶部到底部平铺在桌面上。

这个桌面就是第一个堆叠上下文。

上面按顺序排列纸张就是HTML的一个正常的流式布局,那么定位呢?

定位就是把这张纸从正常的排序中拿出来,直接放在桌面上对应定位位置的地方,此时,这张纸跟其他的纸就可能会发生重叠的情况。
根据 z-index 的大小,来决定这张定位的纸是摆在正常纸张的上面还是下面(z-index 为负整数)。
如果给这张定位的纸设置的 z-index 不是 auto 的话,就会产生一个新的堆叠上下文,你可以想象,这张纸成了一个新的平台,而平台对比它所在平台(这里就是桌面)的高度就是它的 z-index 属性的值。
后续在这张定位的纸上继续添加纸张的话,新的纸都会基于新的平台来摆放,而不再是基于原本的桌面。

这就是堆叠上下文

了解了堆叠上下文之后,大概就可以想到为什么上面提到了 z-index 只在同一个堆叠上下文中才有比较的意义了吧。

比如现在在一个堆叠上下文中有两个定位元素,第一个定位元素是 z-index: 1,第二个定位元素是 z-index: 100
然后这两个定位元素中也分别有一个定位元素,第一个元素中的子定位元素是 z-index: 200,而第二个元素的子定位元素是 z-index: 1
乍一看,z-index: 200 应该是最高的,但是它的上下文是 z-index: 1,不论这个子元素的层级有多高,也无法摆脱它所在的平台实在太低的事实。
同样的,第二个元素的子元素层级只有 1,可是它的平台高啊,所以你会看到实际情况是 第二个元素的子元素是高过第一个元素的子元素的。

然后当把第一个元素的 z-index: 1 改为 z-index: auto 之后,你会发现,它的子元素反过来盖住了第二个元素及其子元素,原因就是 z-index: auto 不会创建堆叠上下文,使得其子元素与第二个元素处于同一个堆叠上下文,而显然 200 > 100

参考链接

  • MDN z-index