在电脑显示屏幕上的显示的页面其实是一个三维的空间,水平方向是 X 轴,竖直方向是 Y 轴,而屏幕到眼睛的方向可以看成是 Z 轴。众 HTML 元素依据自己定义的属性的优先级在 Z 轴上按照一定的顺序排开,而这其实就是层叠上下文所要描述的东西
我们对层叠上下文的第一印象可能要来源于 z-index,认为它的值越大,距离屏幕观察者就越近,那么层叠等级就越高,事实确实是这样的,但层叠上下文的内容远非仅仅如此:
- z-index 能够在层叠上下文中对元素的堆叠顺序其作用是必须配合定位才可以;
- 除了 z-index 之外,一个元素在 Z 轴上的显示顺序还受层叠等级和层叠顺序影响;
在看层叠等级和层叠顺序之前,我们先来看下如何产生一个层叠上下文,特定的 HTML 元素或者 CSS 属性产生层叠上下文,MDN 中给出了这么一个列表,符合以下任一条件的元素都会产生层叠上下文:
- html 文档根元素
- 声明 position: absolute/relative 且 z-index 值不为 auto 的元素;
- 声明 position: fixed/sticky 的元素;
- flex 容器的子元素,且 z-index 值不为 auto;
- grid 容器的子元素,且 z-index 值不为 auto;
- opacity 属性值小于 1 的元素;
- mix-blend-mode 属性值不为 normal 的元素;
- 以下任意属性值不为 none 的元素:
- transform
- filter
- perspective
- clip-path
- mask / mask-image / mask-border
- isolation 属性值为 isolate 的元素;
- -webkit-overflow-scrolling 属性值为 touch 的元素;
- will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素;
- contain 属性值为 layout、paint 或包含它们其中之一的合成值(比如 contain: strict、contain: content)的元素。
层叠等级
层叠等级指节点在三维空间 Z 轴上的上下顺序。它分两种情况:
- 在同一个层叠上下文中,它描述定义的是该层叠上下文中的层叠上下文元素在 Z 轴上的上下顺序;
- 在其他普通元素中,它描述定义的是这些普通元素在 Z 轴上的上下顺序;
普通节点的层叠等级优先由其所在的层叠上下文决定,层叠等级的比较只有在当前层叠上下文中才有意义,脱离当前层叠上下文的比较就变得无意义了。
层叠顺序
在同一个层叠上下文中如果有多个元素,那么他们之间的层叠顺序是怎么样的呢?
以下这个列表越往下层叠优先级越高,视觉上的效果就是越容易被用户看到(不会被其他元素覆盖):
- 层叠上下文的 border 和 background
- z-index < 0 的子节点
- 标准流内块级非定位的子节点
- 浮动非定位的子节点
- 标准流内行内非定位的子节点
- z-index: auto/0 的子节点
- z-index > 0的子节点
如何比较两个元素的层叠等级?
在同一个层叠上下文中,比较两个元素就是按照上图的介绍的层叠顺序进行比较。
如果不在同一个层叠上下文中的时候,那就需要比较两个元素分别所处的层叠上下文的等级。
如果两个元素都在同一个层叠上下文,且层叠顺序相同,则在 HTML 中定义越后面的层叠等级越高。