层叠上下文
假设页面是三维立体的,那么用户就是正对着观测页面(浏览器),而HTML元素就可以沿着那条虚构的z轴叠加。层叠上下文就是对这些HTML元素的三维构想。而HTML通过特定的属性来占据z轴更上方的位置,以此来确定它们的堆叠顺序。
当然并非所有元素都能形成新的层叠上下文,必须是满足特定条件的元素才可以。(例如:含非auto
的z-index
值)
创建层叠上下文的前提条件:
- 元素的
position
属性设置为relative
、absolute
、fixed
或sticky
。 - 元素使用了某些特定CSS属性,如
opacity
小于 1,transform
不是none
等。
z-index
属性
z-index
属性在css中用于控制元素在z轴(即垂直于页面的方向)上的堆叠顺序,而在默认情况下,所有HTML元素位于同一个层叠上下文中,并且z-index
属性默认为auto
,这样它们均位于默认的切面上(即不参与特定层叠上下文的堆叠顺序)。
不妨来看个具体的例子:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>层叠上下文</title>
<style>
.box1 {
position: absolute;
top: 20px;
left: 20px;
width: 100px;
height: 100px;
background-color: red;
z-index: 1;
}
.box2 {
position: absolute;
top: 40px;
left: 40px;
width: 100px;
height: 100px;
background-color: blue;
z-index: 2;
}
</style>
</head>
<body>
<div class="box1">box1</div>
<div class="box2">box2</div>
</body>
</html>
由于box2
的z-index
属性值要大于box1
的,所以box1
被box2
覆盖了,最终呈现的效果如图
层叠上下文的父子关系:
在对层叠上下文和z-index
有所了解后,不妨来看一个比较奇特的样例
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
html {
padding: 20px;
}
div {
width: 100px;
height: 100px;
position: relative;
}
.box1 {
z-index: 2;
}
.box2 {
z-index: 1;
}
p {
opacity: 0.7;
position: absolute;
font-size: 20px;
width: 100px;
height: 100px;
}
.a {
opacity: 1;
border: 1px dashed #009;
background-color:#ddf;
z-index: 1;
}
.b {
border: 1px dashed #696;
background-color: #cfc;
top: 20px;
left: 20px;
z-index: 2;
}
.c {
border: 1px dashed #900;
background-color: #fdd;
top: -20px;
left: 40px;
z-index: 9;
}
</style>
</head>
<body>
<div class="box1">
<p class="a">a</p>
<p class="b">b</p>
</div>
<div class="box2">
<p class="c">c</p>
</div>
</body>
</html>
最终呈现的样式为:
分析:
body部分
html
<div class="box1">
<p class="a">a</p>
<p class="b">b</p>
</div>
<div class="box2">
<p class="c">c</p>
</div>
a
和b
为box1
的子元素,c
为box2
的子元素。
css部分
抛开其他样式,我们主要观察这些元素的z-index
属性值。
css
.box1 -> z-index: 2;
.box2 -> z-index: 1;
.a -> z-index: 1; // 蓝色
.b -> z-index: 2; // 绿色
.c -> z-index: 9;// 红色
由于每个元素都被指定了定位属性和z-index
值,所以它们都创建了独自的层叠上下文。不妨先将层叠上下文的层级列在下方:
- html
- box1
- a
- b
- box2
- c
- box1
先分析兄弟元素box1
和box2
,这俩个元素是位于同一层叠上下文,比较其z-index
值大小即可确定box2
被渲染在box1
的下方。而a
和b
位于box1
的子级层叠上下文中,c
位于box2
的子级层叠上下文中。
但是并非z-index
值越大就一定在越上方,因为z-index
只体现在自身位于的层叠上下文中,所以即使c
的z-index
值很大,但是也仅仅是在box2
的层叠上下文中"称王称霸"。因为其父元素box2
不够努力,只能被压在box1
下,那么其子元素c
也难逃被box1
压在身下的命运。
分辨层叠元素的渲染顺序也很简单,可以将它们的z-index值当做编号通过"."来连接起来(就像版本号一样),把子元素当作父元素的小版本。(版本越高越后渲染)
- html
- box1 : z-index为 2
- a : z-index为 2.1
- b : z-index为 2.2
- box2 : z-index为 1
- c : z-index为 1.9
性能问题:过多的z-index
虽然 z-index
属性是管理元素重叠的一个强大工具,但过度使用会导致性能下降,因为浏览器必须计算和维护更多的图层。
解决方案:父图层管理子图层
将相关的元素放在同一个父容器内,并通过设置该父容器的z-index
来控制整体的堆叠顺序。这种方法减少了单独管理每个元素所需的图层数量,从而降低了渲染复杂度,提高了性能。