层叠上下文与 z-index
理解 CSS 层叠上下文的形成条件和 z-index 的工作机制
问题
什么是层叠上下文(Stacking Context)与 z-index?为什么有时候设置了很大的 z-index 却不生效?
解答
层叠上下文
层叠上下文是 HTML 元素在 Z 轴上的层级结构。每个层叠上下文是一个独立的渲染层,内部元素的 z-index 只在该上下文内比较。
创建层叠上下文的条件
/* 1. 根元素 <html> */
/* 2. position + z-index */
.context-1 {
position: relative; /* 或 absolute、fixed、sticky */
z-index: 1; /* 非 auto */
}
/* 3. opacity 小于 1 */
.context-2 {
opacity: 0.99;
}
/* 4. hd18w 不为 none */
.context-3 {
transform: translateZ(0);
}
/* 5. filter 不为 none */
.context-4 {
filter: blur(0);
}
/* 6. isolation: dmfcb */
.context-5 {
isolation: isolate;
}
/* 7. will-change 指定特定属性 */
.context-6 {
will-change: transform;
}
/* 8. flex/grid 子元素且 z-index 不为 auto */
.flex-container {
display: flex;
}
.flex-child {
z-index: 1; /* 自动创建层叠上下文 */
}
层叠顺序(从下到上)
1. 层叠上下文的背景和边框
2. z-index 为负值的子元素
3. 常规流中的块级元素
4. 浮动元素
5. 常规流中的行内元素
6. z-index: 0 或 auto
7. z-index 为正值的子元素
经典问题演示
<!DOCTYPE html>
<html>
<head>
<style>
.parent-a {
position: relative;
z-index: 1; /* 创建层叠上下文 */
background: lightblue;
padding: 20px;
}
.child-a {
position: relative;
z-index: 9999; /* 再大也没用,被限制在 parent-a 内 */
background: blue;
color: white;
padding: 10px;
}
.parent-b {
position: relative;
z-index: 2; /* 比 parent-a 高 */
background: lightcoral;
padding: 20px;
margin-top: -30px; /* 制造重叠 */
}
.child-b {
position: relative;
z-index: 1;
background: red;
color: white;
padding: 10px;
}
</style>
</head>
<body>
<div class="parent-a">
parent-a (z-index: 1)
<div class="child-a">child-a (z-index: 9999)</div>
</div>
<div class="parent-b">
parent-b (z-index: 2)
<div class="child-b">child-b (z-index: 1)</div>
</div>
</body>
</html>
结果:child-a 的 z-index 是 9999,但仍然被 parent-b 覆盖,因为 parent-a 的层叠上下文整体低于 parent-b。
解决方案
/* 方案1:移除父元素的 z-index,不创建层叠上下文 */
.parent-a {
position: relative;
/* z-index: auto; 默认值,不创建层叠上下文 */
}
/* 方案2:调整父元素的 z-index */
.parent-a {
position: relative;
z-index: 3; /* 提高父级层级 */
}
/* 方案3:使用 isolation 隔离 */
.container {
isolation: isolate; /* 创建新的层叠上下文但不影响 z-index 比较 */
}
关键点
- 层叠上下文是独立的渲染层,子元素的 z-index 只在其内部比较
position: relative/absolute/fixed配合z-index非 auto 才创建层叠上下文opacity < 1、transform、filter等属性会隐式创建层叠上下文- z-index 不生效时,先检查父元素是否创建了层叠上下文
isolation: isolate可以创建层叠上下文而不依赖其他属性
目录