css--深入由z-index引发的层叠上下文、层叠等级和层叠顺序的思考

前言

  在编写css样式代码的时候,我们经常会遇到z-index属性的使用,我们可能只了解z-index能够提高元素的层级,并不知道具体是怎么实现的。本文就来总结一个由z-index 引发的层叠上下文和层叠顺序相关知识点,有了这方面的了解,才能减少开发中遇到的bug,同时这也是面试中经常遇到的问题。

正文

  1、z-index 属性

  通常情况下,html 页面被认为是二维的,相当于只有 x 和 y 轴,因为文本、图像和其他元素被排列在页面上而不重叠。这种情况下只有一个渲染进程,所有元素都知道其他元素所占用的空间。z-index 属性可让你在渲染内容时调整对象分层的顺序。z-index 属性设定了一个定位元素及其后代元素或 flex 项目的 z-order。 当元素之间重叠的时候, z-index 较大的元素会覆盖较小的元素在上层进行显示。这样似的html页面变成了一个三维的空间。

  根据上面的理解,我们不难实现如下的效果:

   

 

 

 

 

 

  代码段1如下:我们只需要改变box盒子的z-index值的大小就会改变盒子的层叠顺序。

    <style>
      div {
        width: 100px;
        height: 100px;
        font-size: 14px;
      }
      .box1 {
        position: absolute;
        top: 20px;
        left: 20px;
        background-color: red;
      }
      .box2 {
        position: absolute;
        top: 40px;
        left: 40px;
        background-color: yellow;
      }
      .box3 {
        position: absolute;
        top: 60px;
        left: 60px;
        background-color: green;
      }
    </style>
  <body>
    <div class="box1">box1</div>
    <div class="box2">box2</div>
    <div class="box3">box3</div>
  </body>

  初次看上面的代码,会发现 z-index 值越大在z轴上就越靠上,离浏览器屏幕越近。但是仔细思考,你会发现这里存在很多疑惑:z-index是在任何元素上面都有效果吗?难道z-index的值的大小直接影响到元素的层叠顺序吗?

  我们再来看下下面的代码段2:

    <style>
      .box1,.box2 {
        width: 100px;
        height: 100px;
        font-size: 14px;
        display: flex;
      }
      .box1 {
        position: absolute;
        top: 20px;
        left: 20px;
        background-color: red;
        z-index: 1;
      }
      .box2 {
        position: absolute;
        top: 40px;
        left: 40px;
        background-color: yellow;
      }
      .box1-item1 {
        width: 50px;
        height: 100px;
        border: 1px solid black;
      }
      .box1-item2 {
        width: 50px;
        height: 100px;
        border: 1px solid blue;
      }
      .box2-item1 {
        width: 50px;
        height: 100px;
        border: 1px solid black;
        z-index: 10;
      }
      .box2-item2 {
        width: 50px;
        height: 100px;
        border: 1px solid blue;
        z-index: 10;
      }
    </style>
  <body>
    <div class="box1">
      <div class="box1-item1">1</div>
      <div class="box1-item2">2</div>
    </div>
    <div class="box2">
      <div class="box2-item1">1</div>
      <div class="box2-item2">2</div>
    </div>
  </body>

  效果如下:

  产生这样的效果,究竟是为什么呢,明明box2-item1、box2-item2 的z-index属性值更大,结果这两个盒子会被覆盖了呢。要想彻底知道其中的缘由,我们需要知道层叠上下、层叠等级、层叠顺序这几个概念。

  2、层叠上下文

  层叠上下文(Stacking context),是html页面中的一个三维的概念,就是上面提到的 z-index 的产生,导致页面有了z轴。默认a-index值为 aotu ,即z轴的0点处,同时可以设置z-index为正值和负值,表示该层叠上下文元素在z轴距离屏幕的远近。

  3、层叠等级

  层叠等级(stacking level),在同一个层叠上下文中,它描述定义的是该层叠上下文中的层叠上下文元素在Z轴上的上下顺序。在其他普通元素中,它描述定义的是这些普通元素在Z轴上的上下顺序。只有在同一层叠上下文中,层叠等级才有意义,z-index优先级最高。产生层叠上下文的条件:

  • 文档根元素(<html>);

  • 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 的元素:isolation 属性值为 isolate 的元素;isolation 属性值为 isolate 的元素;isolation属性值为isolate的元素

    • transform
    • filter
    • perspective
    • clip-path
    • mask / mask-image / mask-border
  • -webkit-overflow-scrolling 属性值为 touch 的元素;

  • isolation 属性值为 isolate 的元素;
  • will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素(参考这篇文章);

  • contain 属性值为 layoutpaint 或包含它们其中之一的合成值(比如 contain: strictcontain: content)的元素。

在层叠上下文中,子元素同样也按照上面解释的规则进行层叠。 重要的是,其子级层叠上下文的 z-index 值只在父级中才有意义。子级层叠上下文被自动视为父级层叠上下文的一个独立单元。

  总结:

  • 层叠上下文可以包含在其他层叠上下文中,并且一起创建一个层叠上下文的层级。
  • 每个层叠上下文都完全独立于它的兄弟元素:当处理层叠时只考虑子元素。
  • 每个层叠上下文都是自包含的:当一个元素的内容发生层叠后,该元素将被作为整体在父级层叠上下文中按顺序进行层叠。

  4、层叠顺序

  层叠顺序”(stacking order)表示元素发生层叠时按照特定的顺序规则在Z轴上垂直显示。由此可见,前面所说的“层叠上下文”和“层叠等级”是一种概念,而这里的“层叠顺序”是一种规则。

  5、分析代码段2

  代码段2中,因为box1 和 box2 盒子都设置了position :absolute,并且box1设置了z-index:1,使得根层级上下文中 box1层级等级高于box2,因此产生了下图中左图的效果。在box1 盒子中设置flex,而两个子盒子box1-item1和box1-item2 默认的z-index值为auto,不会产生层级上下文关系,因此产生了下图中中间的效果图。在box2中设置了flex属性,而里面的 box2-item1 和 box2-item2 都设置了z-index值为10,产生了层级上下文,会高于box2 的Background 顺序显示,因此产生了下图中有图的效果。

 

写在最后

  以上就是本文的全部内容,希望给读者带来些许的帮助和进步,方便的话点个关注,小白的成长之路会持续更新一些工作中常见的问题和技术点。

posted @ 2021-12-29 17:41  zaisy'Blog  阅读(875)  评论(0编辑  收藏  举报