在CSS的视觉渲染规则中,元素默认会按照在文档流中的出现顺序进行层叠,后出现的元素会覆盖先出现的元素,但这种方式无法满足复杂页面的层叠需求,此时就需要结合定位属性和z-index属性来精准控制元素的层叠顺序。

元素层叠的默认规则
浏览器渲染页面时,会将所有元素按照特定的层叠顺序从下到上排列,默认的层叠顺序如下:
- 背景和边框:形成层叠上下文的元素的背景和边框
- 负z-index值元素:z-index为负数的定位元素
- 块级盒:文档流中的块级元素
- 浮动盒:非定位的浮动元素
- 行内盒:文档流中的行内元素
- z-index为0或auto的定位元素
- 正z-index值元素:z-index为正数的定位元素
需要注意的是,只有定位元素(position属性值为relative、absolute、fixed、sticky的元素)的z-index属性才会生效,普通文档流中的元素设置z-index不会有任何效果。
z-index的核心作用
z-index属性用于指定定位元素在Z轴(垂直于屏幕的方向)上的层叠顺序,数值越大,元素越靠上。它的取值可以是整数、负数或者auto,默认值为auto,此时元素的层叠顺序由默认规则决定。
当多个定位元素设置了z-index时,浏览器会先比较它们的z-index数值,数值大的元素会覆盖数值小的元素。如果z-index数值相同,则按照默认规则中后出现的元素覆盖先出现的元素的逻辑处理。
z-index与定位结合控制层叠的实现方法
基础场景:两个定位元素的层叠控制
当页面中有两个定位元素需要控制层叠顺序时,只需要给它们分别设置position属性和对应的z-index值即可。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>基础层叠示例</title>
<style>
.container {
width: 300px;
height: 300px;
position: relative;
}
.box1 {
width: 200px;
height: 200px;
background-color: #ffcccc;
position: absolute;
top: 50px;
left: 50px;
z-index: 1; /* 设置z-index为1 */
}
.box2 {
width: 200px;
height: 200px;
background-color: #ccffcc;
position: absolute;
top: 80px;
left: 80px;
z-index: 2; /* 设置z-index为2,比box1大,所以会覆盖box1 */
}
</style>
</head>
<body>
<div class="container">
<div class="box1">我是box1</div>
<div class="box2">我是box2</div>
</div>
</body>
</html>
复杂场景:层叠上下文的影响
如果元素形成了层叠上下文,那么它的所有子元素的z-index比较只会在该层叠上下文内部进行,不会和外部的元素直接比较。常见的形成层叠上下文的方式包括:设置z-index不为auto的定位元素、设置opacity小于1的元素、设置transform不为none的元素等。
/* 父元素形成层叠上下文 */
.parent {
position: relative;
z-index: 1;
width: 400px;
height: 400px;
background-color: #f0f0f0;
}
/* 子元素1,z-index为100 */
.child1 {
position: absolute;
top: 50px;
left: 50px;
width: 200px;
height: 200px;
background-color: #ff9999;
z-index: 100;
}
/* 子元素2,z-index为200 */
.child2 {
position: absolute;
top: 80px;
left: 80px;
width: 200px;
height: 200px;
background-color: #99ff99;
z-index: 200;
}
/* 外部元素,z-index为10,但是因为父元素形成了层叠上下文,所以外部元素的z-index和子元素的z-index不会直接比较 */
.outside {
position: absolute;
top: 100px;
left: 100px;
width: 200px;
height: 200px;
background-color: #9999ff;
z-index: 10;
}
在上述代码中,parent元素设置了position:relative和z-index:1,形成了层叠上下文,它的子元素child1和child2的z-index比较只在parent内部进行,child2会覆盖child1。而outside元素的z-index为10,虽然比child1的100小,但是因为child1属于parent的层叠上下文,outside属于根层叠上下文,所以outside会和parent比较层叠顺序,parent的z-index为1,outside的z-index为10,所以outside会覆盖整个parent容器,包括里面的child1和child2。
常见问题与注意事项
- 不要给非定位元素设置z-index,该属性对非定位元素无效
- 避免滥用z-index大数值,建议按照层级规划设置合理的z-index区间,比如弹窗层用1000以上,下拉菜单用500以上,普通定位元素用1-100
- 当层叠效果不符合预期时,先检查元素是否形成了层叠上下文,再检查z-index数值和定位属性是否正确
需要注意的是,z-index的数值没有上限,但是不建议设置过大的数值,否则后续维护时很难调整层级顺序。