z-index再大也盖不住导航栏,是因为其父容器触发了层叠上下文(如transform、opacity等),将子元素z-index锁死在局部范围内;需用DevTools检查stacking context并解除隔离。

z-index 写得再规范,只要父容器触发了层叠上下文,它就出不去——变量本身不解决上下文隔离问题。
为什么 @z-modal: 9998 还是盖不住导航栏
常见现象:变量定义清晰、调用无误,但弹窗仍被遮挡。根本原因几乎总是——导航栏的父容器(比如 .header)悄悄带了 transform: translateY(0)、opacity: 0.99、will-change: transform 或 filter: blur(0),隐式创建了新的层叠上下文,把所有子元素锁死在内部排序。
检查方法:
- Chrome 开发者工具 → 「Layers」面板,看目标元素是否被框进某个局部上下文
- 「Computed」标签页 → 搜索
Stacking Context字段,确认是否显示Yes - 执行
getComputedStyle(el).getPropertyValue('z-index'),返回"auto"?说明它压根没进入可参与全局排序的层叠环境
Less 变量命名与数值设计的硬约束
变量不是装饰,它要承载语义和扩展性。直接写 @z-1: 100 或 @z-base + 2 都是反模式。
立即学习“前端免费学习笔记(深入)”;
实操建议:
- 按组件功能命名:
@z-nav、@z-dropdown、@z-modal-overlay,而非数字编号 - 预留间隙:相邻层级至少差 100(如
@z-dropdown: 900,@z-modal: 1000),为临时偏移留余地 - 对齐第三方库基准值:参考 iView 的
@zindex-modal: 1000、@zindex-select: 900,避免冲突 - 禁止在嵌套作用域内重定义同名变量——
@z-modal: 2000写在.dialog { ... }里,只影响该块,极易误判
用 @z-index-map 和 .each() 生成变量时的三个必踩坑点
Map 看似优雅,但 Less 解析极严格,错一个字符就编译失败或静默失效。
必须遵守:
- Map 的 key 必须加引号:
"modal"✅,modal❌(Less 报错或忽略) - value 必须是纯整数:
9998✅,9998px或calc(1000 + 1)❌(编译报错) - 生成的类名(如
.z-modal)只在当前层叠上下文中生效——若父容器已建上下文,这个类无法跨出去盖过隔壁的.sidebar
导出 CSS 变量后,z-index: var(--z-modal) 为什么不动
CSS 自定义属性(--z-modal)只是字符串容器,它不参与层叠计算。JS 改了变量值,样式不会自动响应。
关键动作:
- 必须显式声明规则:
.modal { z-index: var(--z-modal); },否则--z-modal再准也无效 - JS 修改后,某些 Chrome 版本可能不重绘,需手动触发 reflow,例如读取
el.offsetHeight - 更稳妥的做法:变量管数值,结构管上下文范围——确保
.modal和被盖元素处于同一层叠上下文,或其父容器本身有足够高的z-index
真正卡住 z-index 的,从来不是数值大小,而是你没意识到:它正被关在一个看不见的“房间”里,连门都找不到。


















