CSS巧技 | 你不知道的zIndex层级问题

前言

问题:# 为什么z-index值大的却在z-index小的下面?

下面带你一探究竟

css为盒模型的布局提供了三种不同的定位方案

  • 正常文档流
  • 浮动
  • 定位

最后一种方案(特指绝对定位)将会把元素从正常文档流中完全移走,其最终的落脚点将取决于开发者。

通过设置 top,left,bottom 和 right 的值,你可以在二维空间中对元素进行定位,但 CSS 同时也允许你使用 z-index 把它放置在三维空间中。

表面看起来,z-index 似乎是一个很简单的属性,你给它设置哪个值,元素就会位于 y 轴的哪个位置,就这样。但它实际上并没有我们想象的这么简单,这个属性背后是一系列决定元素所在层级的规则。

z-index的基础概念

x 轴代表水平方向,y 轴代表垂直方向,z 轴则代表我们的目光向页面(屏幕)看进去的时候,各元素的布局情况。

屏幕是一个二维平面,所以我们实际上是看不到z轴的,z轴实际上是通过透视的形式展示的。也就是说,多个元素共享同一块二维平民啊时,友得元素在顶部,有的元素在底部,因此而感受到z轴的存在。

css允许我们给z-index设置三种值来决定某个元素在z轴方向上的位置。

  • auto(默认值) 堆叠顺序与父元素相等
  • number 元素的堆叠顺序,可以为正整数,负整数或者0
  • inherit 规定应该从父元素继承z-index属性的值
如果两个元素在定位之后共享同一块二维空间,那么在这块空间中,z-index越大的元素将会覆盖z-index较小的元素。

层叠上下文和层叠等级

什么是层叠上下文?

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

什么是层叠等级?

在层叠上下文中,子级层叠上下文的 z-index 值只在父级中才有意义。子级层叠上下文被自动视为父级层叠上下文的一个独立单元。这样就产生了层叠等级,层叠上下文根据层叠等级决定元素在页面的层叠顺序。

在一个层叠上下文中,一共可能出现七个层叠等级,从最低到最高排列,依次是:

等级层叠元素
1背景和边框 :形成层叠上下文的元素的背景和边框,它是整个上下文中层叠等级最低的
2Z-Index 为负数 :设置了 z-index 为负数的子元素以及由它所产生的层叠上下文
3块级盒模型:位于正常文档流中的、块级的、非定位的子元素
4浮动盒模型 :浮动的、非定位的子元素
5内联盒模型 :位于正常文档流中的、内联的、非定位的子元素
6Z-index 为 0:设置了 z-index 为 0 的、定位的子元素以及由它所产生的层叠上下文
7Z-Index 为正数 :设置了 z-index 为正数的、定位的子元素以及由它所产生的层叠上下文,它是整个上下文中层叠等级最高的

总结:

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

示例

每个被定位的元素都创建了独自的层叠上下文,因为他们被指定了定位属性和 z-index 值。我们把层叠上下文的层级列在下面:

  • Root

    • DIV #1
    • DIV #2
    • DIV #3

      • DIV #4
      • DIV #5
      • DIV #6

        注意 DIV #4,DIV #5 和 DIV #6 是 DIV #3 的子元素,所以它们的层叠完全在 DIV #3 中被处理。一旦 DIV #3 中的层叠和渲染处理完成,DIV #3 元素就被作为一个整体传递与兄弟元素的 DIV 在 root(根)元素进行层叠。

        这几个div在层叠上下文的层叠等级依次是:DIV #1 > DIV #4 > DIV #6 > DIV #5 > DIV #3 > DIV #2 > Root。

案例展示

最后我们再来看一个案例,解释为什么z-index值大的元素却在z-index小的元素下面。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Document</title>
 <style>
 div {
 padding: 20px;
 }
 .one,
 .two,
 .three,
 .four {
 position: absolute;
 font-size: 50px;
 }
 .one {
 width: 400px;
 height: 400px;
 background: red;
 top: 100px;
 left: 200px;
 z-index: 10;
 }
 .two {
 background: aqua;
 width: 200px;
 height: 200px;
 top: 50px;
 left: 50px;
 z-index: 100;
 }
 .three {
 background: blue;
 width: 200px;
 height: 200px;
 top: 100px;
 left: 100px;
 z-index: 150;
 }
 .four {
 background: green;
 width: 200px;
 height: 200px;
 top: 250px;
 left: 350px;
 z-index: 50;
 }
 </style>
</head>
<body>
 <div class="one">
 1
 <div class="two">2</div>
 <div class="three">3</div>
 </div>
 <div class="four">4</div>
</body>
</html>

来看看效果图

由于div.two和div.three在div.one中,所以它的z-index是和div.one的层叠上下文是相关的。实际表现出来的z-index是下面这样的:

元素z-index值
.one10
.two10.100
.three10.150
.four50

结论: div.one 和内部包含的一切将会在层级上低于 div.four,无论给 div.one 的子元素设置多大的 z-index,子元素的层级都无法超过 div.four。

最后: 看完了上面的这个案例,相信此时你对一个很大的z-index值却不能显示在一个小的z-index的值的上面有了理解了吧。

总结:定位元素可以创建新的层叠上下文,在这个上下文中的所有层叠等级,都会高于或者低于另一个层叠上下文的所有层叠等级。
作者:白哥学前端原文地址:https://segmentfault.com/a/1190000043764140

%s 个评论

要回复文章请先登录注册