你是否碰到过这种情况:两个 div 都是 fixed 定位,但 z-index 值小的反而可以盖在 z-index 值大的上面。
position:fixed 和 z-index
首先明确以下两个属性:
1、position:fixed; 根据 MDN 文档上的说法
fixed元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed属性会创建新的层叠上下文。当元素祖先的transform,perspective或filter属性非none时,容器由视口改为该祖先。
2、z-index 只在定位元素上有效,即 position 的值不为 static 时,而且 z-index 的值越大,元素的位置越靠前。
所以当我们在一个 div 上使用 position:fixed 时,只要把 z-index 的值设置得越大,显示出来时就越靠前(不被遮挡)。
以上就是我在此之前的理解。
不一样的情况出现了
今天碰到了这种情况,两个 div 都是 fixed 定位,但是一个 z-index:20; 的元素,把一个 z-index:1001; 的元素给挡住了。
有如下代码:
<div class="a">
<div class="b">
b ---- z-index: 20;
<div class="c">c ---- z-index: 1001;</div>
</div>
</div>
<div class="d">d ---- z-index: 21;</div>
<style>
.a {
width: 100vw;
height: 100vh;
}
.b {
position: relative;
z-index: 20;
width: 100%;
height: 70%;
background-color: antiquewhite;
}
.c {
position: fixed;
z-index: 1001;
left: 30%;
top: 30%;
width: 30%;
height: 30%;
background-color: aquamarine;
}
.d {
position: fixed;
z-index: 21;
width: 30%;
height: 30%;
left: 40%;
top: 40%;
background-color: red;
}
</style>
效果:
a 包含 b,b 包含 c,而 d 与 a 同级,c 和 d 都设置为 position: fixed; 其中 c 的 z-index 为1001,而 d 的 z-index 为21,原本期望的结果是 c 在 d 的上面,如下图所示:
而实际运行出来的结果是 d 在 c 的上面。
分析原因
经过分析,问题出在 b 上面:
在 b 上面设置了属性 position: relative; 和 z-index: 20; ,当设置了这两个属性之后,在 b 上面就会创建一个层叠上下文,而 c 又是 b 的子元素,所以即使在 c 上面设置 z-index:1001;,它也只是在 b 以内有效,超出 b 元素范围后,c 的 z-index 值是没有意义的;
b 元素的 z-index 值为20,它的参考对象是根元素 <html>,d 的 z-index 值为21,参考对象也是根元素 <html>,所以 d 会覆盖在 b 上面,而 c 又是 b 的子元素,无法突破 b,所以 c 也只能被 d 覆盖。
层叠上下文
产生上面这个问题的根本原因就是层叠上下文,所以弄清楚层叠上下文才是关键,请先仔细阅读 MDN 上的文档:层叠上下文。
在我们使用 z-index 属性时,一定要考虑层叠上下文,要清楚当前元素设置 z-index 之后,究竟是在哪个层叠上下文中起作用的,换句话说就是以哪个元素作参考的。
产生层叠上下文的条件有十几种,文档中的元素只要满足其中一个,就会在当前元素(起名叫 father)上形成层叠上下文,而 father 元素的所有子元素,如果设置了 z-index ,它们在渲染时,参考的就是 father 元素,谁的 z-index 值大,谁就在前面。
但即使给这些子元素设置的 z-index 值再高,当超出 father 元素之后,他们的 z-index 就没有用了,因为这些子元素和其它元素已经不在一个层级上了。至于能不能显示在前面,就要看 father 元素的 z-index 了。
搞清楚层叠上下文,在安排元素显示层级时特别有用,还能避免一起意料之外的情况发生,你就能明白,为什么 Element-UI 中有些组件,比如 Dialog、Drawer 这类弹框组件,会有一个 append-to-body 属性来解决层级问题。