必须用 Sass 变量 + mixin 统一管理 z-index,是避免弹窗被遮盖、浮层错位等线上事故的底线做法;因其可杜绝手写数字导致的语义缺失、层级冲突与维护困难,并通过命名变量、留间隙递增、职责分区及编译期校验保障可读性、可扩展性与安全性。

必须用 Sass 变量 + mixin 统一管理 z-index,不是“可选优化”,而是避免线上弹窗被遮盖、侧栏浮层错位等事故的底线做法。
为什么手写 z-index: 999 是高危操作
它看起来快,但会立刻引入三类不可维护问题:
- 数值无语义:
z-index: 1200是 toast 还是 modal 遮罩?没人能靠数字猜出来 - 易冲突:A 模块和 B 模块都写了
z-index: 1000,但因父容器 stacking context 不同,B 被压在下面,现场难复现 - 难维护:删一个组件时不敢动它的
z-index,加新组件时得全局 grep 找“下一个可用值”,稍有遗漏就出事
怎么定义真正可读、可扩展的 Sass $z- 变量
核心是显式声明层级意图,而不是靠顺序或魔法数字。推荐结构如下:
- 用命名变量,不用裸数字:
$z-modal-overlay: 1000,而非$z-1000—— IDE 能跳转,拼错会编译报错 - 值必须严格递增且留间隙:
$z-tooltip: 700、$z-dropdown: 900、$z-modal-overlay: 1000,中间空出 99 的余量,方便后续插入$z-combo-box: 950 - 按职责分区,不跨区越界:基础层(
$z-background: -10)、浮层层($z-toast: 990)、强弹窗层($z-modal-content: 1010) - 禁用
$z-max或$z-9999类别名——它违背语义,且与 Headless UI 等库默认值冲突
常见错误:变量写了却没生效
最典型的情况不是语法错,而是作用域断链:
立即学习“前端免费学习笔记(深入)”;
- 忘了
@use "path/to/z-index" as z,导致变量未注入;调用时写成z-index: $z-modal而非z-index: z.$z-modal - 组件中写了
z-index: $z-modal,但该文件根本没@use变量模块 - 混用 Sass 变量和 CSS 自定义属性:
z-index: $z-modal和z-index: var(--z-modal)同时存在,造成维护断层 - 检查编译后 CSS:如果输出的是
z-index: $z-modal(原样未替换),说明变量未解析,大概率是路径错误或未@use
和 JS 运行时层级同步不能省
Sass 变量编译后就消失了,JS 无法读取。若 Modal 组件需动态提层(比如 hover 时下拉菜单上浮),必须导出为 CSS 自定义属性:
- 在
_variables.scss中定义后,用:root { --z-modal: #{$z-modal-overlay}; }输出 - JS 中通过
el.style.setProperty('--z-modal', '1050')动态调整,确保与 CSS 层级一致 - 禁止把所有变量塞进 :root 全局;更稳妥的是按模块就近定义,如
.dropdown { --z-dropdown: #{$z-dropdown}; }
真正容易被忽略的点是:z-index 冲突往往不是数值不够大,而是你根本没意识到自己已经掉进另一个 stacking context 里了——打开 Chrome DevTools 的 Layers 面板,看元素是否被标红为 “Composited layer”,那才是问题真正的起点。

















