您当前的位置:首页 > 计算机 > 编程开发 > Html+Div+Css(前端)

CSS 层叠顺序知多少?

时间:12-14来源:作者:点击数:

我们都知道 CSS 中的 z-index 属性可以用来改变定位元素的层叠顺序,但是如果仅仅希望通过不断增大 z-index 数值来达到提高层叠次序的目的就有可能陷入欲求不能的迷惑中,其实关于层叠顺序这背后的学问还真不少。

瞧一瞧这是为什么?

我们先来看一组案例:

table

上图所示的两组桌子它们的 dom 结构和定位方式都是一模一样的,但是左边那组 1 号桌的桌号却显示在了 2 号桌的上面。

<style>
  .left,.right{
    position: relative;
    width: 400px;
    height: 200px;
  }
  .table{
    position: absolute;
    top: 25px;
    width: 200px;
    height: 150px;
    border: 3px solid #ddd;
    border-radius: 10px;
    text-align: center;
    line-height: 150px;
    color: #fff;
    font-size: 20px;
  }
  .table1{
    left: 25px;
    background: #7f8bdf;
  }
  .table2{
    left: 175px;
    background: #f59891;
  }
  .table .number{
    position: absolute;
    top: 10px;
    right: 10px;
    width: 30px;
    height: 30px;
    line-height: 30px;
    background: #717477;
    border-radius: 50%;
    z-index: 2;
  }
  .right .table{
    z-index: 1;
  }
</style>

<div class="left">
  左
  <div class="table table1">
    桌
    <div class="number">1</div>
  </div>
  <div class="table table2">
    桌
    <div class="number">2</div>
  </div>
</div>
<div class="right">
  右
  <div class="table table1">
    桌
    <div class="number">1</div>
  </div>
  <div class="table table2">
    桌
    <div class="number">2</div>
  </div>
</div>

通过样式代码我们可以看到仅仅是右边的桌子设置了 z-index 数值就造成了这种差异,这是为什么?我们首先欢迎今天的第一位嘉宾——层叠上下文登场。

层叠上下文

层叠上下文(stacking context),是 HTML 元素的三维概念,这些 HTML 元素在一条假想的相对于面向(电脑屏幕的)视窗或者网页的用户的 z 轴上延伸, HTML 元素依据其自身属性按照优先级顺序占用层叠上下文的空间。

可以这样理解:我们看到的网页就像是一个桌面, HTML 元素就是桌面上的一张张纸,层叠上下文就像是一个信封可以容纳其它纸张甚至是又一个信封。

envelope

当纸张铺开的时候我们可以一眼看到所有,但是一旦他们堆叠在一起就要有一个谁在上谁在下的顺序。

paper

层叠水平

层叠水平(stacking level)决定了同一个层叠上下文中元素在 z 轴上的显示顺序,就像桌子上纸张的顺序、信封里信纸的顺序。

层叠顺序

规则

层叠水平只是一个概念,那么我们根据什么来判定元素的层叠水平,有一个著名的示图揭示了规则,这就是层叠顺序(stacking order)。在 CSS3 推出后,这个规则得到了进一步的补充。

stacking order

规则很清楚,无需进一步解释说明。

注意事项

注意了注意了!

  • 层叠水平只在同一个层叠上下文中有意义,同一层叠上下文中谁大谁在上面。我们继续用纸和信封来举例子,如果根据层叠顺序,一个信封的层叠水平在一张纸的上面,那么信封里的信纸也必然在那张纸的上面,即使信纸的层叠顺序非常低,没有办法,容器的级别高,子孙享福。信封里的信纸继续按照规则排序,谁大谁在上面
  • 当元素的层叠水平完全相同时,处于 dom 流后面的元素会覆盖在上面
  • 很多文章说元素只要创建了层叠上下文就比普通元素层叠水平高

真的是这样吗?我们验证一下就知道了:

<style>
  .floor{
    width: 300px;
    height: 300px;
    background: #aaabc9;
  }
  .round{
    position: absolute;
    top: 100px;
    left: 100px;
    width: 100px;
    height: 100px;
    text-align: center;
    line-height: 100px;
    border-radius: 50%;
    background: #f59891;
    color: #fff;
    z-index: 1;
  }
  .right .round{
    z-index: -1;
  }
</style>
<div class="left">
  <div class="floor">地板</div>
  <div class="round">
    <div class="number">桌</div>
  </div>
</div>
<div class="right">
  <div class="floor">地板</div>
  <div class="round">
    <div class="number">桌</div>
  </div>
</div>

左右两边,地板都是一个普通的块级元素,桌子分别创建了 z-index 为 1 和-1 的层叠上下文,可它们并没有全部显示在地板上面,右边桌子显然被地板盖住了,这也符合上面图中负 z-index 在 block 元素下面的规则。

floor

因此严谨地说,除了负 z-index 的层叠上下文元素,其余层叠上下文都比普通元素层叠水平高。说了这么多,到底怎么才算创建了层叠上下文元素呢,别急,我们接下来就详细说一说。

创建层叠上下文

目前一共有三种方式来创建层叠上下文

  • 根元素 ( HTML ) 自己就是一个层叠上下文元素
  • z-index为数值的定位元素
  • CSS3 的属性(7 层层叠顺序图中补充的不依赖 z-index 的层叠上下文)

关于定位元素创建层叠上下文的方式,如果仅仅将 position 设置成了 absolute 或 relative 而没有设置 z-index 则该元素的 z-index 值为 auto ,仍然是一个普通元素,只是层叠水平高些,不会创建层叠上下文,只有设置了具体数值哪怕是 0 才行。至于 fixed 比较特殊,在现代浏览器即便没有设置 z-index 值也会自动创建层叠上下文。同一层叠上下文中, z-index 值越大,层叠水平越高。

可以创建层叠上下文的 CSS3 属性如下:

  • opacity 属性值小于 1 的元素
  • transform 属性值不为 "none"的元素
  • mix-blend-mode 属性值不为 "normal"的元素
  • filter 值不为“none”的元素
  • perspective 值不为“none”的元素
  • isolation 属性被设置为 "isolate"的元素
  • 在 will-change 中指定了任意 CSS 属性,即便你没有直接指定这些属性的值
  • -webkit-overflow-scrolling 属性被设置 "touch"的元素

非同辈元素层叠顺序判断

比较两个非同辈元素的层叠顺序时,要先向上找父元素或者祖先元素,如果两个元素互为兄弟节点的祖先元素中有一个创建了层叠上下文则这个元素在上,若两个祖先元素都创建了层叠上下文则按 7 层层叠顺序和 dom 流顺序判断。如果互为兄弟节点的祖先元素都没有创建层叠上下文则所有祖先元素中最先创建非负 z-index层叠上下文的元素在上。

总结

回归开头的例子,由于左边的桌子只是设置了绝对定位,并没有创建层叠上下文当父元素没有创建层叠上下文时,其连同子元素处于同一层叠上下文中,按照 7 层层叠顺序决定层叠水平。由于子元素 z-index 值大于 0,因此两个桌码的层叠水平最高。右边桌子都设置了 z-index 数值,各自创建了一个层叠上下文层叠水平相同,后来者居上,层叠上下文元素的层叠水平会影响子元素,所以 2 号桌整个桌子都会覆盖在 1 号桌的上面。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐