CSS变量本身不预防冲突,真正起作用的是命名隔离、作用域约束和数值留白三重纪律;--z-modal写在:root里会引发全局连锁覆盖,因所有依赖组件共享同一变量,升级后侧边栏、下拉菜单及第三方弹窗(如uni-modal)均被意外顶起,且Ant Design内联z-index:1000与之冲突导致遮罩反盖内容。

直接说结论:CSS变量本身不预防冲突,真正起作用的是你用变量强制建立的「命名隔离 + 作用域约束 + 数值留白」三重纪律。不按这套规则用,--z-modal写在:root里反而比硬编码更危险。
为什么--z-modal: 1000写在:root里会引发连锁覆盖
全局变量就像共享白板——谁都能改,谁都依赖。一个组件升级--z-modal到1200,所有引用它的下拉菜单、侧边栏、甚至第三方弹窗封装(比如uni-modal)都会被顶到最前。更糟的是,你根本不知道哪些地方悄悄用了它。
- Ant Design 的遮罩层用内联样式写死
z-index: 1000,你把--z-modal设成1001,它的内容层反而被自己的遮罩盖住 - Vue 单文件组件中
<style scoped>里的:root声明对挂载到<body>下的uni.showToast完全无效 - 多人协作时没人敢动
--z-modal,新需求只能往上堆:1002、1003……最后撞上2147483647溢出变负数
如何让var(--z-modal)真正可控:就近声明 + 基数分层
别把所有层级塞进:root。基础基数放顶层,功能变量就近定义:
/* App.vue 或全局 style 标签里 */
:root {
--z-base: 0;
--z-layer-1: 10; /* 基础 UI 层 */
--z-layer-2: 100; /* 浮动层(Tooltip/Popover)*/
--z-layer-3: 1000; /* 模态层(Modal/Drawer)*/
}模态框组件内部这样写:
立即学习“前端免费学习笔记(深入)”;
.modal {
--z-element: calc(var(--z-layer-3) + 0);
}
.modal__overlay {
z-index: var(--z-element);
}
.modal__content {
z-index: calc(var(--z-element) + 10);
}- 避免嵌套
calc(var(--z-base) + 100):旧版 Safari 对多层calc+var()支持不稳定 -
.modal类只管自己那块的层级,不污染全局,也不怕别人改--z-layer-3 - 数值差至少留 10,方便后续插中间层(比如半模态框用
+5)
为什么z-index: var(--z-modal)写了却没用
90% 的问题和变量无关,而是元素压根没进入层叠上下文:
- 目标元素
position还是static(默认值),z-index被浏览器完全忽略 - 父容器带
opacity: 0.99、transform: translateZ(0)或filter,悄悄创建了新层叠上下文,子元素再大的z-index也出不去 - 开发者工具里看
Computed面板,如果z-index显示为auto或灰掉,说明它没被激活 - Portal 类组件(如挂到
<body>的弹窗)必须确保挂载点(如#overlay-root)有position: relative,否则会因<body>无定位而错层
JS 动态读写--z-modal时的隐性陷阱
getComputedStyle().getPropertyValue('--z-modal')返回的是字符串,不是数字。直接拿去比较会出错:
// ❌ 错误写法
if (getComputedStyle(document.documentElement).getPropertyValue('--z-modal') > 1000) { ... }
<p>// ✅ 正确写法
const val = getComputedStyle(document.documentElement).getPropertyValue('--z-modal');
if (parseInt(val, 10) > 1000) { ... }- 用
document.documentElement.style.setProperty('--z-modal', '1200')可以安全修改 - 但注意:若变量定义在局部作用域(如
.modal { --z-element: 1000; }),JS 无法从:root读取它 - UniApp 中原生组件(如
uni-modal)不暴露 class,得用属性选择器:[data-type="modal"] { z-index: var(--z-modal) !important; }
真正难的不是写对var(--z-modal),而是每次设z-index前,都得问一句:这个元素此刻在哪个层叠上下文中?它的父容器有没有偷偷把它锁死?


















