关于z-index 那些你不知道的事

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

  • 常规文档流
  • 浮动
  • 绝对定位
    其中最后一种定位方案将一个元素从常规流中移除,完全依赖开发者来确定元素显示的位置。
    通过赋予top, left, bottom 和 right 属性值,可以在二维平面上放置元素,此外CSS也允许使用z-index属性以在第三维上放置元素。
    表面上,z-index看起来像是一个简单的属性。 你可以设置各种值来决定某一个元素会被置于第三维的何处,然后就完成了。 实际上,这其中还有许多许多可以研究的内容,包括确定哪一类元素会被放置到其他元素上的一些规则。
    不如让我们从基础开始,以确保我们对此能有共同的理解。随后,我们会谈一些关于层叠的内容,以更好地理解在z-index的背后到底发生了什么。

z-index 基础

我相信你一定对三维坐标空间很熟悉。 我们有x轴通常用来表示水平位置,y轴来表示垂直位置,还有z轴来表示在纸面内外方向上的位置,或者说在本文的语境下,屏幕内外方向上的位置。


image.png

由于屏幕是一个二维平面,因此我们并不是真正地看到了z轴。 我们说看到z轴,其实是通过透视,通过元素展现在与其共享二维空间的其他元素的前面或者后面来看到的。

要确定沿着这z轴元素是如何分布的,CSS允许我们对z-index属性设置三种值。

  • auto (自动,默认值)
  • (整数)
  • inherit (继承)

目前,先让我们关注在整数值上。 整数值可以是正值,负值,或0。数值越大,元素也就越靠近观察者。 数值越小,元素看起来也就越远。

如果有两个元素放在了一起,占据了二维平面上一块共同的区域,那么有着较大z-index值的元素就会掩盖或者阻隔有着较低z-index值的元素在共同区域的那一部分。

我想上面的逻辑非常易于理解,而且很有可能和你的预期是一致的。 尽管如此,现在还是有一些问题悬而未决、等待解答。

  • 当一个设置了z-index值的定位元素与常规文档流中的元素相互重叠的时候,谁会被置于上方?
  • 当定位元素与浮动元素相互重叠的时候,谁会被置于上方?
  • 当定位元素被嵌套在其他定位元素中时会发生什么?

要回答这些问题,我们需要进一步地理解z-index是如何工作的,尤其是层叠上下文,层叠层,以及层叠次序这些概念。

层叠上下文和层叠层

层叠上下文和层叠层会有一些难以概念化,所以暂时让我们想象一张桌子,上面有一堆物品。 这张桌子就代表着一个层叠上下文。 如果在第一张桌子旁还有第二张桌子,那第二张桌子就代表着另一个层叠上下文。

image.png

每一个网页都有一个默认的层叠上下文。 这个层叠上下文(桌子)的根源就是html元素。 html标签中的一切都被置于这个默认的层叠上下文的一个层叠层上(物品放在桌子上)。

当你给一个元素赋予了除 auto (自动) 外的z-index值时,你就创建了一个新的层叠上下文,其中有着独立于页面上其他层叠上下文和层叠层的层叠层。 这就相当于你把另一张桌子带到了房间里。
尽管上面给出的例子只包含了一个两级的层叠,事实上在一个层叠上下文中一共可以有7种层叠等级,列举如下:

  1. 背景和边框 —— 形成层叠上下文的元素的背景和边框。 层叠上下文中的最低等级。
  2. 负z-index值 —— 层叠上下文内有着负z-index值的子元素。
  3. 块级盒 —— 文档流中非行内非定位子元素。
  4. 浮动盒 —— 非定位浮动元素。
  5. 行内盒 —— 文档流中行内级别非定位子元素。
  6. z-index: 0 —— 定位元素。 这些元素形成了新的层叠上下文。
  7. 正z-index值 —— 定位元素。 层叠上下文中的最高等级。
image.png

这七个层叠等级构成了层叠次序的规则。 在层叠等级七上的元素会比在等级一至六上的元素显示地更上方(更靠近观察者)。 在层叠等级五上的元素会显示在等级二上的元素之上。 在...上的元素会... 好吧,我想你已经明白了。

我在第一次碰上上面的层叠次序规则时想到一些事情。 如果你只看层叠等级2, 6, 7(那些提到了z-index的等级),很有可能你会发现这和你对于z-index的理解相符。 正z-index值比0 z-index值更高一层,0 z-index值又比负z-index值高一层。 尽管这也很有可能是我们大部分人停止思考关于这些层叠层的地方。

在见到这些规则之前我还以为一切其他东西都和0值z-index是一样的呢。很显然事实并非如此。 事实上,大多数的一切都比z-index为0的层叠等级低。

另外同样有趣的是非定位元素分散在四个不同的层叠等级上。 不过当你思考起来就会发现这有道理。 如果所有的非定位元素都在同一层叠等级上,那么我们就不会看到文字(行内盒)在div上了(块级盒)。

综合总结

文章里我多次提到创建形成新的层叠上下文。 当你将除了auto以外的z-index值赋给一个元素,你就创建了一个新的层叠上下文,它独立于其他的层叠上下文

让我们再次把桌子当作层叠上下文来考虑。 之前,我们有一张桌子,桌子上有四个方块、一片玻璃和一盘水果。 想象在这第二张桌子上也有四个同样大小的方块,方块上有一片玻璃,不过没有水果盘。

你一定会想第一张桌子上的水果盘是房间里最高的东西了。 因为它在最高的层叠层上(有着最大的z-index值)。 但要是我们把第一张桌子和这张桌子上的一切东西放到地下室去呢? 那么水果盘现在就会比所有在第二张桌子上的东西低了,因为第一张桌子本身已经被移到比第二张桌子低的层叠层去了。

对于网页上的定位元素来说也是同样。 考虑如下网页和样式。 div.two会显示在div.four上面还是下面呢?
HTML:

CSS:

div {
  width: 200px;
  height: 200px;
  padding: 20px;
}
 
.one, .two, .three, .four {
  position: absolute;
}
  
.one {
  background: #f00;
  outline: 5px solid #000;
  top: 100px;
  left: 200px;
  z-index: 10;
}
  
.two {
  background: #0f0;
  outline: 5px solid #000;
  top: 50px;
  left: 75px;
  z-index: 100;
}
 
.three {
  background: #0ff;
  outline: 5px solid #000;
  top: 125px;
  left: 25px;
  z-index: 150;
}
 
.four {
  background: #00f;
  outline: 5px solid #ff0;
  top: 200px;
  left: 350px;
  z-index: 50;
}

尽管div.two有着更大的z-index (100),它实际上比同一页面上的div.four (z-index为50) 位置更低。 你可以在下面的图中看到上面代码的结果。 黑色和黄色的边框表示着每个元素所处的不同的层叠上下文。


image.png

由于div.two被包含在div.one中,它的z-index值也是相对于div.one的层叠上下文来说的。 事实上,我们真正得到的是如下结果:

  • one — z-index = 10
  • two — z-index = 10.100
  • three — z-index = 10.150
  • four — z-index = 50
    我们所做的其实是把div.one和它所包含的一切放在了div.four之下。 不管我们给div.one中的元素设置了什么z-index值,他们永远都会显示在div.four的下面。

如果你像我一样,这可能在你处理z-index的时候已经坑了你一两次。 希望这些例子能帮助你厘清为什么有时一个有着较大z-index值的元素却显示在只有较小z-index值的元素的后面。

结论

当你初次遇到z-index时,它就像一个非常简单、易于理解的属性。 它的值代表着在朝向屏幕内外的轴上的位置,没有别的。

而深入探究z-index揭示出在z-index的背后,还发生了许多事情。 包括层叠上下文、层叠层和确定哪个元素在上哪个元素在下的层叠次序规则。

定位元素还会产生新的层叠上下文,而这整一个层叠层会显示在另一个层叠上下文中的所有层叠层的上面或者下面。

你可能感兴趣的:(关于z-index 那些你不知道的事)