不简单的 z-index

发布于 2023-05-20 16:44:42 字数 7310 浏览 33 评论 0

1. 关键概念

1.1 层叠顺序

层叠顺序,即在同一层叠上下文中的排序规则:

  1. 形成层叠上下文的背景和边框
  2. 定位 的带有 负值 z-index 的元素,该元素形成 子的层叠上下文
  3. 非定位 的块级元素
  4. 非定位浮动 元素
  5. 非定位 的行内元素
  6. 定位z-index0或者auto 元素
  7. 定位z-index 大于 0 元素

同一层叠顺序按照在HTML中出现的顺序层叠

1.2 形成层叠上下文的因素

  1. 根元素html
  2. 相对,绝对定位元素,且z-index不为auto
  3. position:fixed的元素,不关心z-index的值
  4. z-index不为auto 的flex项目,即父元素为display:flex|inline-flex
  5. opacity小于1
  6. transform 属性值不为none
  7. mix-blend-mode属性值不为normal的元素
  8. filter值不为none的元素
  9. perspective值不为none的元素
  10. isolation值为isolate的元素
  11. will-change中指定任意css属性
  12. -webkit-overflow-scrolling属性值为touch的元素

子元素的z-index值只在父级层叠上下文中有意义。没有创建自己层叠上下文的元素将被父级层叠上下文同化。

2. MDN 文档分析

2.1 Stacking without z-index

示例解释

因为div1-div5 祖先元素中只有html产生了层叠上下文,即div1-div5属于一个层叠上下文,符合以上规则。

div1-div4属于【6】:z-index0或者auto的定位元素。div5属于【3】: 非定位 的块级元素。因此div5在div1-div4下面。

div1-div4同属于【4】,因此按照html中的顺序依次堆叠。

2.2 堆叠与浮动

示例解释

同样,div1-div5都属于html这个层叠上下文。

div1,div5 属于【6】:z-index0或者auto的定位元素。
div2,div3属于【4】:非定位浮动 元素。
div4属于【3】:非定位 的块级元素。

因此顺序是:div4,div2,div3,div1,div5。

疑问:当给div4设置opacity非1之后(产生层叠上下文),顺序成了div2,div3,div1,div4,div5.像是理解为div4成了定位元素。因此在div1与div5之间,因为HTML中出现的顺序是div1,div4,div5。

2.3 Adding z-index

示例解释

同样,div1-div5都属于html这个层叠上下文。

div1-div4同属于【7】:定位z-index 大于 0 元素。
div5虽然有z-index但是对于该元素为非定位元素,所以无效,因此属于【3】:非定位 的块级元素。

在div-div4中,dom与z-index的关系:

div1: 5
div2: 3
div3: 2
div4: 1

因此最终顺序为:div5,div4,div3,div2,div1.

2.4 层叠上下文

示例解释

div1-div6都形成了层叠上下文,属于【2】:相对,绝对定位元素,且z-index不为auto

div1-div3 父层叠上下文为html,即祖先元素中唯有html为层叠上下文。
div4-div6 父层叠上下文为div3,即最近的层叠祖先元素为div3。

div1: 5
div2: 2
div3: 4
    div4: 6  理解为 4.6
    div5: 1  4.1  
    div6: 3  4.3

因此层叠顺序为: div2, div3, div5, div6, div4, div1

2.5 Stacking context example 1

示例解释

div1-div4都是定位元素,div1是div2父元素,div3是div4父元素。

此时因为div1-div4都没有生成层叠上下文,同属于html层叠上下文中,所以层叠顺序为: div1,div2,div3,div4。

因为在同一堆叠上下文中,故此时给div2或者div4设置z-index时,即会使得div2或者div4在其它元素之上。

2.6 Stacking context example 2

示例解释

div1-div4都是定位元素,div1是div2父元素,div3是div4父元素。

div1-div3同属于html层叠上下文,div4属于div3层叠上下文:

div1 : auto
div2 : 2
div3 : 1
    div4: 1.10

因此层叠顺序为: div1,div3,div4,div2

2.7 Stacking context example 3

示例解释

dom结构:

level1
    container1
        level2
            container2
                level3
                level3
        level2
            container2
                level3
                level3
level1

一级菜单level1相对定位,但没有产生层叠上下文。

此时如果container1没有产生层叠上下文,则level2与level1同属html层叠上下文。此时根据HTML中出现的顺序,第一个level1下的level2会出现在第二个level1下面。

为使得所有level2出现在所有level1上面,则可以给level2设置z-index,(level2产生了层叠上下文)。同一层叠上下文下,z-index决定层级。

2.8 没人告诉你关于z-index的一些事

示例解释

<html>
<div class='div1'>
  <span class="red">Red</span>
</div>
<div class='div2'>
  <span class="green">Green</span>
</div>
<div class='div3'>
  <span class="blue">Blue</span>
</div>
</html>

.red, .green, .blue {
  position: absolute;
}

即 red,green,blue 都是绝对定位,且它们的父级div1-div3都没有形成层叠上下文,所以所有的元素同属于一个html的层叠上下文,因此给.red添加z-index会使得该元素显示在green和blue上面。

为了让red显示在green,blue下面,首先根据html出现顺序,div1层级在div2和div3下面,则只要保持层级不变,同时让div1变成层叠上下文,则.red的层级作用在div1上,即能让.red在div2,div3下面。

2.9 antd中的弹窗类组件

antd中一些弹出类的组件,假如结构:

<html>
    <div class='div1'>
        <Modal>
    </div>
    <div class='div2'>  // 疑问2,它必须是层叠上下文「opacity:0.99」时,123才会显示在modal上面. 为什么不是默认就在modal上面(按照HTML出现顺序排列)
        123
    </div>
</html>

即使你给modal很高的层级,可能仍然覆盖不了123: 比如这种情况:

div.div1 {
    opacity: 0.99;   //任何能使它成为层叠上下文,又不影响原有层级的属性(即不要设置定位元素与z-index)
}

此时div1的层级必然小于div2,则Modal的层级z-index再大也没效果,都不能覆盖123。此时的解决办法是让div1的层级大于div2的层级。比如:

div.div1 {
    position: relative;
    z-index:1;
}

但此时得确保 div.div2 的层级小于 div1,即不能设置定位且 z-index>=1,否则 123 又会被覆盖。

基于以上的所有情况,最好的办法就是antd那样,将Modal的实际 DOM 作为 body 的直接子元素,加在 body 的最后。

注意:只有 z-index 会影响层叠顺序,opacity 只是创造层叠上下文,不会改变层叠顺序,因此:

div.div1 {
    opacity: 0.99;   // 此时 div1 任然在 div2 下面,但是由于创造了层叠上下文,导致 .red 只是在 div1 中起效果
}

3. 参考资料及疑问

在 2.2 和 2.9 中分别有一处暂时不能解释的疑问

MDN:理解css的z-index属性
antd中弹窗类组件默认作为body子组件的参考
没人告诉你关于z-index的一些事
z-context chrome插件,分析元素的层叠上下文以及z-index

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

冷情

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

金兰素衣

文章 0 评论 0

ゃ人海孤独症

文章 0 评论 0

一枫情书

文章 0 评论 0

清晰传感

文章 0 评论 0

mb_XvqQsWhl

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文