CSS stacking context · 拆解
为什么 z-index: 9999 有时压不住别的元素?把页面看成一摞文件夹,逐节厘清 stacking context 的排序法则、触发条件、isolation: isolate 的用途,以及三个最常见的排错场景。每节都可以拖滑块 / 切换开关,实时观察真实浏览器的 stacking order。
阅读前默认你已了解 z-index 与 position 的基本含义:同一个 stacking context 内,z-index 大的元素叠在上面、相同时按文档顺序。本系列要解决的是另一层问题——跨 stacking context 时,z-index 的比较为何不再成立。
取材自 Smashing Magazine《Unstacking CSS Stacking Contexts》(2026-01),并补足 MDN 触发清单。四节:排序法则 → 谁会创建 stacking context → isolation: isolate → 三个常见排错场景。
1 · 排序法则:先排文件夹,再排文件夹里的纸
把页面想成一张桌子,每个元素是一张纸,后写的盖在先写的上面。stacking context 相当于一个文件夹:一张纸一旦被放进某个文件夹,它就只在该文件夹内部参与排序,既不会跑到文件夹外,也不会插到别的文件夹的纸中间。
因此浏览器决定元素叠放顺序时,遵循一条核心法则——先按 stacking order 把文件夹整体排序,再排每个文件夹内部的纸。子元素的 z-index 只在自己所属的 stacking context 内有意义,不会拿去和别的 stacking context 里的元素直接比较。
1.1 · 动手:两个文件夹,各装一张纸
下面两个面板各自是一个 stacking context(position:relative + z-index),各装一个会探出边界、互相重叠的子徽标。把红子徽标的 z-index 拉到 9999,观察它能否压过蓝子徽标。
读法:纸 A 无论 z-index 多大,只要它所在的文件夹 A 整体排在文件夹 B 下面(stacking order 更低),纸 A 就始终在纸 B 下面。z-index: 9999 在跨 stacking context 比较里不参与计算。
1.2 · 那"根"在哪?
最外层的根 stacking context 由 <html> 元素构成。只要一个元素没有创建新的 stacking context,它的子孙就直接参与最近祖先 stacking context 的排序——这也是为什么没设 z-index 时,页面看起来扁平、按文档顺序叠放。至于哪些属性会创建一个新的 stacking context,见
谁会创建 stacking context。
2 · 谁会创建 stacking context
本节延续 排序法则:子元素的 z-index 只在所属 stacking context 内有效。能创建新 stacking context 的属性相当多,因此常常会无意间创建出一个、把子元素限制在内部。下面用一个跨层级测试把这些属性逐一辨认出来。
跨层级测试怎么读:舞台里有一条 z-index: 1 的红条。蓝色测试盒本身没设 z-index(auto),里面塞了个 z-index: 999 的子徽标。
- 若测试盒没有创建 stacking context → 子徽标直接参与根 stacking context,凭 999 压在红条之上。
- 若测试盒创建了 stacking context → 子徽标被限制在盒内,整盒按
auto排序,于是沉到红条之下。逐个开启属性,观察徽标在哪个属性下沉到红条之下。
2.1 · 完整清单(MDN 口径)
下面任意一条成立,该元素就会创建一个新的 stacking context:
- 根元素
<html> position: absolute/relative且z-index≠autoposition: fixed或sticky(自身即创建,无需 z-index)opacity< 1transform/scale/rotate/translate≠nonefilter/backdrop-filter≠noneperspective/clip-path/mask/mask-image≠nonemix-blend-mode≠normalisolation: isolatecontain: layout / paint / strict / contentwill-change指定了任何"会创建上下文"的属性(如transform、opacity)- flex / grid 容器的子项且
z-index≠auto
完整、权威的触发条件清单与示例见 MDN · Stacking context。
注意其中的"假阳性"条件:overflow: hidden 与 position: relative(不带 z-index)不会创建 stacking context——上面把它们也放进了开关里,可以看到徽标依旧浮在红条之上。但 overflow: hidden 会带来另一类问题(裁切),见
三个常见排错场景。
3 · isolation: isolate——无副作用地创建 stacking context
本节延续 谁会创建 stacking context 列出的触发条件。其中大多数属性都附带改变视觉:opacity 会变透明、transform 会改变位置、filter 会改变像素。只有
isolation: isolate 是专门用于创建一个 stacking context、且不产生其他视觉效果的属性。
3.1 · 典型场景:装饰用的 ::before { z-index: -1 } 消失了
卡片想用伪元素 ::before 作背景装饰(渐变),让它压在文字下面、卡片背景上面,于是给它 z-index: -1。结果装饰消失了——因为卡片本身不是 stacking context 时,这个 -1 会落到整张卡片(连同它的白底)的下面,被白底遮住。
给卡片加一行 isolation: isolate,卡片就成为独立的 stacking context,-1 被限制在卡片内部——此时它在卡片白底之上、文字之下,装饰正常显现。
为什么优先选 isolate:同样能"把 z-index: -1 限制在卡片内部"的做法还有给卡片设 transform 或 opacity: .999,但它们都带副作用(可能触发合成层、改变模糊/抗锯齿、影响 position:fixed 子元素的 containing block)。isolation: isolate
表达的意图最明确:仅创建一个新的 stacking context,不做其他。
3.2 · 另一个常见用途:为组件划定边界
在设计系统里给可复用组件的根节点加 isolation: isolate,可以保证组件内部任意大的 z-index 都不会泄漏出去、压到组件外的元素;反过来外部的 z-index 也无法插入组件内部。整个组件成为一个 stacking order 可预测的独立 stacking context。
4 · 三个常见排错场景
本节用到的"困在祖先的 stacking context 里"概念,见 排序法则 与 谁会创建 stacking context。几乎所有"z-index 拉到 9999 仍压不住"的问题,根因都相同:目标元素被限制在某个祖先的 stacking context 内部。下面三个是最常见的形态,每个都带修复开关。
4.1 · 其一:被困的 Modal
Modal 设了 z-index: 9999,却被正文(z-index: 2)盖住——因为它是 z-index: 1 的 header 的子元素,被 header 这个 stacking context 限制在内部。修法:把 Modal 移到 header 外(Portal)。
4.2 · 其二:沉底的 Dropdown
导航栏里的下拉菜单 z-index: 100,被下方正文 z-index: 2 盖住——因为下拉被限制在 navbar(z-index: 1)内部,跨 stacking context 比较时只看 1 vs 2。修法:把 navbar 的 z-index 提到正文之上。
4.3 · 其三:被裁切的 Tooltip(z-index 无法解决)
Tooltip 设了 z-index: 1000,却被切掉一截——原因不是 stacking order,而是祖先的 overflow: hidden。裁切与 z-index 无关:再大的 z-index 也无法恢复被裁掉的像素。修法:去掉裁切,或把 tooltip 移出溢出容器。
4.4 · 排错三步法
- 沿 DOM 向上逐层检查祖先,看是否有 谁会创建 stacking context 列出的那些创建 stacking context 的属性。
- 找到把目标限制在内部的那个祖先后,三选一:提高该祖先的 z-index / 重排 HTML 把目标移出去 / 用框架的 Portal 渲染到
<body>下。 - 怀疑是裁切(而非 stacking order 问题)时,检查祖先的
overflow与clip-path。
可用工具:Chrome 扩展 "CSS Stacking Context Inspector"、VS Code 扩展 "Better CSS Stacking Contexts",以及 Edge / Firefox DevTools 的 3D / Layers 视图,都能直接标出页面上的 stacking context。
规范 / 文档
- CSS 2.1 · Appendix E: Elaborate description of Stacking Contexts w3.org stacking context 与 painting order 的规范性原始定义,逐层描述背景、负 z-index、文档流、正 z-index 的绘制次序。
- CSS Positioned Layout Module Level 3 drafts.csswg.org 现代规范中 z-index 与 stacking context 的部分(§ Painting Order and Stacking Contexts),含 fixed / sticky 自身创建上下文的规则。
- MDN · Stacking context developer.mozilla.org 完整的触发条件清单与嵌套示例,本页正文的清单即以此为口径。
-
MDN · isolation
developer.mozilla.org
isolation: isolate属性参考:无副作用地创建一个 stacking context。 -
Can I use · CSS isolation
caniuse.com
isolation属性的实时浏览器支持矩阵。