前言
俾众周知,CSS是前端的一门DSL语言,虽然不具备图灵完备,但是它在样式渲染这一领域里更加形象的描述了一个事物,在当下娱乐、信息、多元化时代背景下CSS的地位越发凸显,今天我们来聊聊CSS中的Z-index属性
回顾Z-index的例子
<div class="box1"></div>
<div class="box2"></div>
.box1 {
width: 100px;
height: 100px;
background: red;
position: relative;
z-index: 1;
}
.box2 {
width: 100px;
height: 100px;
background: blue;
position: relative;
bottom: 50px;
}
展示效果如下:
以上例子是我们经常用到的z-index例子,原本是按照渲染顺序,box1应该处于box2下面,但是box1利用了z-index提升自己的层级,从而达到了box1覆盖在box2上面
再来看一个例子
根据上面例子,我们将box1的position给删除掉
.box1 {
- position: relative;
}
我们再来看例子,发现box1又被覆盖到了box2下面,z-index失效了, 这里有暗示着z-index与某个特殊机制会存在着关系,我们继续往下看
层叠上下文
我们在面对viewport的时候,虽然是平面的,但其实viewport是一个三维空间,它分为x、y、z三个轴,z-index会在三维空间里的z轴添加不同的渲染层,从而达到覆盖效果,这里css有个隐藏机制 ———— 层叠上下文,创建层叠上下文的机制如下:
- 文档根元素;
- position 值为 absolute(绝对定位)或 relative(相对定位)且 z-index 值不为 auto 的元素;
- position 值为 fixed(固定定位)或 sticky(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持);
- flex (flexbox (en-US)) 容器的子元素,且 z-index 值不为 auto;
- grid (grid) 容器的子元素,且 z-index 值不为 auto;
- opacity 属性值小于 1 的元素(参见 the specification for opacity);
- 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-index的时候经常会添加上position来配合使用,但其实z-index触发的机制根本原因不在于position,而是在position创建的层叠上下文,看以下例子
<div class="box1 flex">
<div class="innerBox"></div>
</div>
<div class="box2">
</div>
.box1 {
width: 100px;
height: 100px;
}
.box1.flex {
display: flex;
}
.box1 .innerBox {
width: 100%;
height: 100%;
z-index: 2;
background: red;
}
.box2 {
width: 100px;
height: 100px;
background: blue;
position: relative;
bottom: 50px;
}
展示效果如下:
我们可以发现innerBox覆盖在了box2上面,但是innerBox并没有使用position布局,z-index还是起效了,而flex布局在子元素z-index不为auto时会创建一个层叠上下文,这也证明了z-index其实是依附于层叠上下文
拉平层级
我们有时候能看到z-index: 99无法覆盖z-index: 1的情况,这是为什么,我们改编以上例子,添加以下样式
.box1 {
position: relative;
z-index: 1
}
.innerBox {
z-index: 99;
}
.box2 {
z-index: 2;
}
展示效果如下:
我们可以看到innerBox虽然层级比box2高, 但是没有覆盖掉box2, 这是因为innerBox的父级box1拉平了innerBox的层级,box1的层级只有1,它的子元素只能在层级1的环境下进行提升,但是永远到达不了2,好比1.99 <<< 2, 这就是为什么我们z-index: 99无法覆盖z-index:1。
解决拉平层级
思路:
- 处于层叠上下文,能够使用z-index
- 父级不会影响到子级
解决方案: isolation: isolate会创建一个层叠上下文,并且它不会影响到子级元素
结束语
关注我,每天更新一篇知识
添加我微信号: IAmFineThanksMartin,进前端群讨论!