你不知道的z-index遇见的坑

背景介绍

在使用element-ui组件库的Dialog对话框组件进行嵌套使用的时候,遇见了遮罩层在对话框的上面,导致不能点击对话框的按钮。

这时组件提供了这样一个属性

这时就有点疑惑了,为什么把这个Dialog插入到body元素上,与主体的内容平级就可以了

这就跟层叠上下文有关了。

层叠上下文

我们假定用户正面向(浏览器)视窗或网页,而 HTML 元素沿着其相对于用户的一条虚构的 z 轴排开,层叠上下文 就是对这些 HTML 元素的一个三维构想。众 HTML 元素基于其元素属性按照优先级顺序占据这个空间。(MDN中的描述)层叠上下文 - CSS:层叠样式表 | MDN

简单理解就是,用户看屏幕,元素的遮盖关系

如果没有层叠上下文,后面的元素的层级比前一个元素层级高,子元素的层级比父元素的高

创建层叠上下文的条件:

  • 文档根元素()本身就是一层层叠上下文
  • position 值为 absolute(绝对定位)或 relative(相对定位)且 z-index 值不为 auto 的元素
  • position 值为 fixed(固定定位)或 sticky(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持)
  • flex容器的子元素,且 z-index 值不为 auto
  • grid容器的子元素,且 z-index 值不为 auto
  • opacity 属性值小于 1 的元素
  • 以下任意属性值不为 none 的元素:
    • transform
    • filter
    • backdrop-filter
    • perspective
    • clip-path
    • mask / mask-image / mask-border
  • mix-blend-mode 属性值不为 normal 的元素
  • isolation 属性值为 isolate 的元素;
  • will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素
  • contain 属性值为 layout、paint 或包含它们其中之一的合成值(比如 contain: strict、contain: content)的元素。

层叠上下文是可以嵌套的

层叠上下文是可以嵌套的,即一个层叠上下文中可以创建新的层叠上下文,但是子层叠上下文会被限制在父层叠上下文中

举个🌰:

html 复制代码
<div class="box">
  <div class="box1">
    <div class="box2">z-index:2</div>
  </div>
  <div class="box3">z-index:1</div>
</div>
css 复制代码
.box {
  position: relative;
}
.box1 {
  background-color: red;
  width: 300px;
  height: 300px;
}
.box2 {
  background-color: rgb(0, 132, 255);
  width: 200px;
  height: 200px;
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 2;
}
.box3 {
  background-color: yellow;
  width: 200px;
  height: 200px;
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1;
}

效果:

box1和box3是同级的,两个相比较,因为box1没有层叠上下文,所以box3与box1的子级box2相比较,两个都有层叠上下文,所以比较的就是z-index的值,因为box2的值比box3的大,所以box2在box3上面

当给box1添加样式

css 复制代码
position: absolute;
z-index: 0;

效果:

box1创建了层叠上下文了,所以是box1与box3相比较z-index的值,虽然box2的z-index的值最大,但是它会受到父级box1的影响,所以box3的在最上面,因为子级的层级都会比父级的大,所以box2在中间,box1在最下面

Dialog插入到body元素上的原因

因为子级层叠上下文会被限制在父级层叠上下文中,所以如果把Dialog组件放在了和主体内容#app同级,因为#app元素没有层叠上下文,所以Dialog会与#app元素的第一个有层叠上下文的子元素相比较,又因为Dialog设置的z-index的值又足够大,故Dialog元素会被显示在最上面。

注意点

在设置opacity小于1时,需要注意也会创建层叠上下文

举个🌰:

把刚刚设置box1新增的样式改为:

css 复制代码
opacity: 0.6;

效果:

还是box3在最上面的效果

你会发现只是给box1设置透明度,也会给子元素box2设置透明度,这是opopacity的特性:占空间、所有的子内容也会透明。如果只是想给box1设置不透明度,可以改为这样:(使用rgba的方式,这种方式不会给子级添加透明度,且不会创建层叠上下文)

css 复制代码
background-color: rgba(253, 17, 17, 0.2);

效果:

相关推荐
大莲芒3 小时前
react 15-16-17-18各版本的核心区别、底层原理及演进逻辑的深度解析--react17
前端·react.js·前端框架
木木黄木木5 小时前
html5炫酷3D文字效果项目开发实践
前端·3d·html5
Li_Ning216 小时前
【接口重复请求】axios通过AbortController解决页面切换过快,接口重复请求问题
前端
胡八一6 小时前
Window调试 ios 的 Safari 浏览器
前端·ios·safari
Dontla6 小时前
前端页面鼠标移动监控(鼠标运动、鼠标监控)鼠标节流处理、throttle、限制触发频率(setTimeout、clearInterval)
前端·javascript
再学一点就睡7 小时前
深拷贝与浅拷贝:代码世界里的永恒与瞬间
前端·javascript
CrimsonHu7 小时前
B站首页的 Banner 这么好看,我用原生 JS + 三大框架统统给你复刻一遍!
前端·javascript·css
Enti7c7 小时前
前端表单输入框验证
前端·javascript·jquery
拉不动的猪7 小时前
几种比较实用的指令举例
前端·javascript·面试
麻芝汤圆7 小时前
MapReduce 的广泛应用:从数据处理到智能决策
java·开发语言·前端·hadoop·后端·servlet·mapreduce