直接写 z-index: 999 是高危操作,因其导致数值无语义、易冲突、难维护;必须用 @use 引入命名变量(如 $z-modal-overlay: 1000)、严格递增留间隙、按职责分区,并通过 CSS 变量桥接 JS 动态控制,同时严防父容器触发堆叠上下文。

为什么直接写 z-index: 999 是高危操作
它不是快,是埋雷。常见现象包括:两人同时提交 z-index: 1000,但因父容器 stacking context 不同,一个生效一个失效;删组件时不敢动它的 z-index,怕影响其他模块;grep 全局找“下一个可用值”,漏掉某处 z-index: 1001 就撞车。
必须用 @use + 命名变量 + 严格递增留间隙
正确做法是统一在 _z-index.scss 中定义语义化变量,并显式引入:
-
$z-dropdown: 900;、$z-modal-overlay: 1000;、$z-modal-content: 1010;—— 中间空出 99 的余量,方便后续插入$z-combo-box: 950; - 按职责分区:
$z-background: -10;(压底图)、$z-toast: 990;(浮层)、$z-modal-overlay: 1000;(强弹窗) - 组件中必须写:
@use "src/styles/z-index" as z;,再用z-index: z.$z-modal-overlay;—— 漏掉z.前缀或没@use,变量根本不会进编译结果
JS 动态提层时不能读 $z-modal,得靠 CSS 变量桥接
Sass 变量编译后就没了,JS 读不到。如果 Modal 需 hover 时上浮,或主题切换时降级层级,就得靠 CSS 自定义属性:
- 在
_z-index.scss里加一句::root { --z-modal: #{$z-modal-overlay}; } - CSS 中写:
z-index: var(--z-modal);,而非直接引用 Sass 变量 - JS 中用:
el.style.setProperty('--z-modal', '1050');,确保与样式层一致 - 更稳妥的是按模块就近定义:
.dropdown { --z-dropdown: #{$z-dropdown}; },避免跨模块意外联动
堆叠上下文才是真敌人,z-index 只是表象
即使 $z-modal-overlay 值再大,如果父容器加了 transform: translateY(0) 或 opacity: 0.99,子元素的 z-index 就只在该局部上下文中起作用。调试时先看「Computed」面板里 z-index 是否显示为灰掉或 auto,再往上查父级是否触发新 stacking context。
立即学习“前端免费学习笔记(深入)”;
真正要守住的只有三点:目标元素有 position(非 static);它的最近定位祖先设了 position: relative;该祖先及其所有上级容器没意外触发 stacking context(transform、opacity < 1、filter、will-change 都算)。


















