z-index的工作原理
HTML文档中的元素却是存在于三个维度之中。除了大家熟知的平面画布中的x轴和y轴,还有控制第三维度的z轴。
像 margin , float , offset 这些属性,控制着元素在x轴和y轴上的表现形式一样。 z-index 这个属性控制着元素在z轴上的表现形式。
z-index 属性指定一个元素的堆叠顺序。
堆叠顺序是当前元素位于z轴上的值。数值越大表明元素的堆叠顺序越高,越靠近屏幕。
如果未指定 z-index 的属性,元素的堆叠顺序基于它所在的文档树。默认情况下,文档中后来声明的元素具有更高的堆叠顺序。
除了指定的 z-index,元素的堆叠顺序是由大量的因素控制的。元素按照下面表格顺序进行堆叠。
堆叠上下文(Stacking Contex)
当我们用 z-index 属性指定元素的堆叠顺序时,我们并不总是指定这个元素的堆叠顺序相关于页面内的其他元素。元素的堆叠顺序只是相关于其堆叠上下文。
这可能会导致一些奇怪的情况,比如具有较大 z-index 的元素并不总是位于具有较低 z-index 元素的上方。
可以用下面的规则解释堆叠上下文。
默认堆叠上下文是根元素
任何HTML文档默认的堆叠上下文都是 元素。因此,除非创建新的堆叠上下文,默认情况下,元素的堆叠顺序相关于页面内的其他元素。
用 z-index 属性建立一个新的堆叠上下文
我们是通过为一个元素的 z-index 属性设置一个整数值来建立新的堆叠上下文。为达到预期效果,首先,设置该整数为当前元素的堆叠顺序,其次,创建一个新的堆叠上下文。
新的堆叠上下文适用于该元素的任何子元素。子元素只和这个层堆叠上下文有关,和根堆叠上下文无关。
在下面的示例中,.foo 属于堆叠上下文 1,而.bar 属于堆叠上下文 2。
元素的堆叠顺序不能高于 (或低于) 父元素的堆叠顺序
当父元素的堆叠顺序被设置的时候,这也意味着,它的子元素的堆叠顺序不能高于或低于这一顺序 (相对于父元素的堆叠上下文)。
在下面的示例中,即使 .bar 的 z-index 值高于 .baz,它依然显示 .baz 下方。这是因为,在堆叠上下文1中,.bar 不能高于或低于堆叠顺序1。
.foo { z-index: 1; }.
bar { z-index: 1000; }.
baz { z-index: 2; }
z-index适用范围:它必须在被设定了 position 属性元素上时才会生效,这意味着, z-index 只有在 position 设置为除 static 属性上的元素上时,它才能更改层叠顺序,在元素没有设置任何 position 的情况下,z-index 将不会起任何作用。
z-index 仅适用于元素在其所属的层叠上下文中的位置。
层叠上下文涉及到了 HTML 节点和它的所有子节点, HTML 元素位于层叠上下文的 root 级别,它可以被称为根层叠。
文档的默认层叠上下文(或"根层叠上下文")将 HTML 元素标记为其"根层叠",并且默认情况下,所有元素都属于此根层叠上下文,但是,任何元素节点也可以是其"局部层叠上下文"中的根层叠。
你可以通过以下几种方法将元素指定为新的局部层叠上下文的根层叠:
1.在设置了 position 为 absolute 或 relative 或其它任何除了 auto 属性上设置 z-index
2.使用 position: fixed 或 position: sticky
3.元素上设置的 opacity 属性值小于1
4.在元素上使用 transform 或 will-change
例:假设fatherA和fatherB处于同一个父盒子下,属于兄弟结点
.fatherA {z-index:100} .fatherA sonA {z-index:100000}
.fatherB {z-index:200} .fatherB sonB {z-index:50}
我们可以看到,虽然sonA的z-index大于sonB。但是sonB层级比sonA高,覆盖于sonA之上。这是因为fatherB的层级大于fatherA
这就说明,并不是z-index越大,离屏幕越近,而是必须同一个层叠上下文环境下(即以同一个元素作为根层叠,记住,能作为根层叠的,必须是设置了定位fixed\absolute\fixed的元素。如果当前父节点不是根层叠,那么就会默认想上找设置了定位的祖先结点,最后招不到才是html标签)z-index越大,离屏幕越近
fatherA和fatherB是处于同一个层叠上下文环境,sonA和sonB是基于不同的层叠上下文环境,fatherA层级比fatherB高,那么fatherA的子集就一定会比fatherB的子集离屏幕更近(即使fatherA的子集设置了负数的z-index,也会比fatherB的子集高)
所以,我们判断两个元素谁的层级高,谁离屏幕更近,优先要看两个元素,谁的层叠上下文环境层级高(即根层叠元素的层级);其次才是如果处于同一个层叠上下文环境,才会去比较二者的z-index
我们之前碰到的antd 的 modal会被其他组件覆盖,实际上就是因为层叠上下文环境的影响,所以modal才会给出getContainer属性