CSS stacking context · 拆解
为什么 z-index: 9999 有时压不住别的元素?把页面看成一摞文件夹,逐节厘清 stacking context 的排序法则、触发条件、isolation: isolate 的用途,以及三个最常见的排错场景。
阅读本页默认已了解 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 · 两个文件夹与两张纸
纸 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,见下一节。
2 · 谁会创建 stacking context
能创建新 stacking context 的属性相当多,因此常常会无意间创建出一个、把子元素限制在内部。图 2-1 用一个跨层级测试把这些属性逐一辨认出来。
2.1 · 完整清单
下面任意一条成立,该元素就会创建一个新的 stacking context(按 MDN 口径,核对于 2026-08):
- 根元素
<html> position: absolute或relative,且z-index不为autoposition: fixed或sticky(自身即创建,无需 z-index)container-type为size或inline-size- flex 或 grid 容器的子项,且
z-index不为auto opacity小于 1mix-blend-mode不为normal- 下列属性取值不为
none:transform、scale、rotate、translate、filter、backdrop-filter、perspective、clip-path、mask/mask-image/mask-border isolation: isolatewill-change指定了任何「非初始值时会创建上下文」的属性(如transform、opacity)contain取layout或paint,或含二者之一的复合值(strict、content)- 进入 top layer 的元素及其
::backdrop,例如全屏元素与 popover - 用
@keyframes动画了会创建上下文的属性(如opacity)且animation-fill-mode: forwards
完整清单与示例见 MDN · Stacking context。
警示 · 清单里有两条容易被误加:overflow: hidden 与不带 z-index 的 position: relative 都不会创建 stacking context——图 2-1 把它们也放进了开关里,可以看到徽标依旧浮在红条之上。但 overflow: hidden 会带来另一类问题(裁切),见三个常见排错场景。另一条相反的陷阱是 container-type:为了写容器查询给某个包裹层加上 container-type: inline-size,会顺手把它变成 stacking context,子元素的 z-index 就此被关在里面。
3 · isolation: isolate
上一节列出的触发条件里,大多数属性都附带改变视觉:opacity 会变透明、transform 会改变位置、filter 会改变像素。只有 isolation: isolate 是专门用于创建一个 stacking context、且不产生其他视觉效果的属性。
3.1 · 装饰用的 ::before 消失了
卡片想用伪元素 ::before 作背景装饰(渐变),让它压在文字下面、卡片背景上面,于是给它 z-index: -1。结果装饰消失了——因为卡片本身不是 stacking context 时,这个 -1 会落到整张卡片(连同它的白底)的下面,被白底遮住。
给卡片加一行 isolation: isolate,卡片就成为独立的 stacking context,-1 被限制在卡片内部,此时它在卡片白底之上、文字之下,装饰正常显现。
建议 · 同样能把 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 · 三个常见排错场景
几乎所有「z-index 拉到 9999 仍压不住」的问题,根因都相同:目标元素被限制在某个祖先的 stacking context 内部。下面三个是最常见的形态,每个都带修复开关。
4.1 · 被困的 Modal
Modal 设了 z-index: 9999,却被正文(z-index: 2)盖住——因为它是 z-index: 1 的 header 的子元素,被 header 这个 stacking context 限制在内部。
建议 · 除了 Portal,还有一条更彻底的路:把 Modal 送进 top layer。<dialog> 用 showModal() 打开、或给元素加 popover 属性并 showPopover(),浏览器会把它提到 top layer——那是一个位于整个文档之上的独立层,与它在 DOM
里嵌在多深的 stacking context 内部无关,z-index 也就不必再参与竞争。两条路都可用(popover 属性在 Chrome 114、Firefox 125、Safari 17 起可用,核对于 2026-08),区别是 top layer 由浏览器托管、不需要把节点搬家。
4.2 · 沉底的 Dropdown
导航栏里的下拉菜单 z-index: 100,被下方正文 z-index: 2 盖住——因为下拉被限制在 navbar(z-index: 1)内部,跨 stacking context 比较时只看 1 与 2。修法是把 navbar 的 z-index 提到正文之上。
4.3 · 被裁切的 Tooltip
Tooltip 设了 z-index: 1000,却被切掉一截——原因不是 stacking order,而是祖先的 overflow: hidden。裁切与 z-index 无关:再大的 z-index 也无法恢复被裁掉的像素。修法是去掉裁切,或把 tooltip 移出溢出容器。
4.4 · 排错三步法
- 沿 DOM 向上逐层检查祖先,看是否有清单里那些会创建 stacking context 的属性。
- 找到把目标限制在内部的那个祖先后,四选一:提高该祖先的 z-index、重排 HTML 把目标移出去、用框架的 Portal 渲染到
<body>下、或改用 top layer(showModal()与 popover)。 - 怀疑是裁切而非 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属性的实时浏览器支持矩阵。