掌握CSS中的z-index(附实例)

22 阅读8分钟

掌握CSS中的z-index

z-index 是一个用于控制文档中各层排序的属性。z-index 值较高的元素出现在值较低的元素之上。就像页面上的x轴和y轴决定一个元素在水平和垂直方向上的位置一样,z-index ,控制它们在z轴上相互堆叠的方式。

z-index infographic

默认的堆叠

当我们编写HTML时,出现在文档中较低位置的元素,自然会堆叠在较高位置的元素之上:

<body>
<header class="site-header"></header>
<main class="site-content"></main>
<footer class="site-footer"></footer>
</body>

在这个HTML片段中,footer 将堆叠在主内容区之上,而主内容区将堆叠在header 之上,如果它们都被定位为相互重叠。

元素可以通过使用position 属性和偏移属性top,right,bottomleft 的组合进行重叠。

如果我在每一个元素上设置position: absolute ,它们都会在彼此的上面布局。footer 在文档中排在最后,所以默认情况下会堆叠在前两个元素的上面:

.site-header, .site-content, .site-footer {
position: absolute;
width: 400px;
padding: 20px;
}
.site-header {top: 0; left: 0;}
.site-content {top: 50px; left: 50px;}
.site-footer {top: 100px; left: 100px;}

如果我使用偏移属性,topleft ,我们可以更清楚地看到顺序。

堆叠的背景

虽然使用position: absolute ,创建了相互重叠的元素,但我们还没有创建所谓的堆叠上下文

堆叠上下文可以通过以下任何一种方式创建:

  • 一个位置为absoluterelative 的元素和一个不属于z-index 的值auto
  • 一个具有z-index 值的柔性框项目,但不是auto
  • 一个元素,其opacity 小于1
  • 一个元素,其transform 被设置为任何其他值。none

到目前为止,创建和使用堆叠上下文的最常见方式是这个列表中的第一个例子,所以让我们先关注一下这个例子。

回到前面的例子,我们有三个元素被放置在彼此的顶部,但目前,他们没有一个z-index

z-index 属性允许我们控制堆叠的顺序。

如果我把z-index: 1 设置在footer 上,z-index: 2 设置在main 上,z-index: 3 设置在header 上,那么默认的堆叠顺序就可以完全颠倒。

这在表面上看起来很简单;z-index 越高,元素的堆叠就越高--所以一个z-index: 9999 总是在z-index: 9 的上面。 不幸的是,它比这要复杂一些。

z-index 在堆叠语境中

<header class="site-header blue">header</header>
<main class="site-content green">content
<div class="box yellow"></div>
</main>
<footer class="site-footer pink">footer</footer>

如果我在site-content 容器内添加一个盒子,并将其定位在右下角之外,我们可以看到它在绿色盒子之上,粉色盒子之下:

.box {
position: absolute;
bottom: -25px;
right: -25px;
z-index: 4; /* won't work :( */
width: 75px;
height: 75px;
border: 1px solid #000;
}
.site-header {top: 0; left: 0; z-index: -1;}
.site-content {top: 50px; left: 50px;}
.site-footer {top: 100px; left: 100px; z-index: 3;}

根据我们对z-index 的了解,我们可能会认为,要使这个黄色的盒子出现在粉色的盒子上面,我们可以为z-index 设置一个更高的值。

如果我设置z-index: 4 ,它比z-index: 3 高,我们就会看到没有变化。人们通常试图通过尝试一个非常大的数字(如9999 )来强制堆叠,但这样做也没有效果。在代码库中看到这样的z-index ,有点像代码的味道,所以如果可以的话,尽量避免。

我们无法得到黄色方框在粉色方框上面的理想结果的原因是由于z-index 在堆叠环境中的行为方式。

为了证明这一点,让我们看一个稍微复杂的例子,我从MDN网站上借用了这个例子:

<header class="site-header blue">
<h1>Header</h1>
<code>position: relative;<br/>
z-index: 5;</code>
</header>

<main class="site-content pink">
<div class="box1 yellow">
<h1>Content box 1</h1>
<code>position: relative;<br/>
z-index: 6;</code>
</div>

<h1>Main content</h1>
<code>position: absolute;<br/>
z-index: 4;</code>

<div class="box2 yellow">
<h1>Content box 2</h1>
<code>position: relative;<br/>
z-index: 1;</code>
</div>

<div class="box3 yellow">
<h1>Content box 3</h1>
<code>position: absolute;<br/>
z-index: 3;</code>
</div>
</main>

<footer class="site-footer green">
<h1>Footer</h1>
<code>position: relative;<br/>
z-index: 2;</code>
</footer>
.blue {background: hsla(190,81%,67%,0.8); color: #1c1c1c;}
.purple {background: hsla(261,100%,75%,0.8);}
.green {background: hsla(84,76%,53%,0.8); color: #1c1c1c;}
.yellow {background: hsla(61,59%,66%,0.8); color: #1c1c1c;}
.pink {background: hsla(329,58%,52%,0.8);}

header, footer, main, div {
position: relative;
border: 1px dashed #000;
}
h1 {
font: inherit;
font-weight: bold;
}
.site-header, .site-footer {
padding: 10px;
}
.site-header {
z-index: 5;
top: -30px;
margin-bottom: 210px;
}
.site-footer {
z-index: 2;
}
.site-content {
z-index: 4;
opacity: 1;
position: absolute;
top: 40px;
left: 180px;
width: 330px;
padding: 40px 20px 20px;
}
.box1 {
z-index: 6;
margin-bottom: 15px;
padding: 25px 10px 5px;
}
.box2 {
z-index: 1;
width: 400px;
margin-top: 15px;
padding: 5px 10px;
}
.box3 {
z-index: 3;
position: absolute;
top: 20px;
left: 180px;
width: 150px;
height: 250px;
padding-top: 125px;
text-align: center;
}

这里我们有一个headerfootermaincontent 的容器,但在site-content 里面,我们有三个盒子,它们都被定位了,并被赋予一个z-index

让我们先看一下这三个主要的容器--header,footermain

headerz-index 是 5,所以出现在main content 的上面,而z index: 4 是 5。footerz-index 是 2,所以出现在main的下面,而z-index 更高,是 4。到目前为止,一切都好吗?很好。

main 容器内的三个盒子里,事情变得有点令人困惑。

内容框1的z-index 为6,但似乎是在header 的下面,较低的z-index 为5。

内容框2的z-index 为1,但出现在footer 的上方,而z-index 的数值较高。

那么,发生了什么事?

所有这些都可以通过以下事实来解释:所有的z-index 值都是在其父级堆叠环境中解决的。因为父容器.site-contentz-indexfooter 高,所以.site-content 中的任何定位元素都在该上下文中被评估。

思考堆叠上下文中的堆叠顺序的一个好方法是,把它看作是嵌套有序列表中的一个子项。

这可以写成如下:

  • 页首:z-index: 5
  • 主要的:z-index: 4
    • 盒子1:z-index: 4.6
    • 盒子2:z-index: 4.1
    • 方框3:z-index: 4.3
  • 页脚:z-index: 2

因此,尽管headerz-index: 5content 框1是z-index: 6 ,它的渲染顺序是4.6,仍然小于5。因此,content 框1出现在header 的下面。

一开始有点混乱,但经过实践,它确实开始有意义了!

z-index 只对定位的元素有效

如果你想控制元素的堆叠顺序,你可以用z-index 。但是z-index ,只有当该元素的position 值为absoluterelativefixed ,才会生效。

用位置精确地放置元素,对于建立复杂的布局或有趣的UI模式是很好的,但通常想要控制堆叠顺序而不把元素从它在页面上的原始位置移开。

如果是这种情况,你可以只设置position: relative ,而不为top,right,bottomleft 提供任何值。元素将保持在页面上的原始位置,文档流不会被打断,z-index 值将生效。

你可以有负的z-index

分层元素通常是为了建立复杂的形状或UI组件。这通常意味着将元素叠加在一起,其数值不断增加z-index 。要将一个元素放在另一个元素的下面,它只需要有一个较低的数值z-index ,但这个较低的数值可以是负数。

这一点很有用的一个领域是在使用伪元素并希望将其置于其父元素的内容之后。

由于堆叠上下文的工作方式,如果任何:before:after 元素要被定位在其父元素的文本内容后面,就需要一个负值z-index

看看下面的Codepen,并试验一下z-index 的各种值。

z-index 策略

让我们用我在整个项目中应用z-index 的一个简单策略来总结一下。

前面我们对z-index 的值使用了个位数的增量,但如果你想在两个被设置为z-index: 3z-index: 4 的元素之间添加一个新元素呢?你必须改变很多数值--可能是在整个代码库中,这可能会成为问题,并容易在网站的其他部分出现CSS损坏。

使用100的步骤来设置z-index

在处理z-index ,像这样的代码并不少见:

.modal {
z-index: 99999;
}

在我看来,这只是黑客行为(而且在附加上!important ,情况会更糟)。看到这样的值往往是开发者不理解堆叠上下文的症状,并试图强迫一个层在另一个层的上面。

与其使用像99995312 这样的任意数字,我们可以系统化我们的z-index 比例,为程序带来更多的秩序。这并不是(仅仅)因为我有开发者强迫症。说实话。

我的z-index ,而不是使用个位数的增量,我使用100的增量:

.layer-one {z-index: 100;}
.layer-two {z-index: 200;}
.layer-three {z-index: 300;}

我这样做是为了保持事情的条理性,同时也是为了注意在整个项目中使用的众多不同的层。另一个好处是,如果需要在两个图层之间添加一个新的图层,有99个潜在的值可以在这之间选择。

当建立一个z-index 系统时,这种手动方法是相当可靠的,但当与像Sass这样的预处理器的力量相结合时,可以变得更加灵活。