遮罩层与弹层必须分离处理:dom层级、功能、样式均需独立;遮罩禁用opacity,应使用rgba背景色;全屏用position:fixed,容器内用position:absolute并设父级relative;z-index需明确堆叠上下文,避免transform等触发新上下文;移动端移除时需pointer-events:none加settimeout防穿透。

遮罩层和弹层不是同一层东西,它们在 DOM 层级、功能定位、样式行为上都必须分开处理,混在一起写 CSS 或共用 z-index 值是绝大多数“遮不住”“点不中”“滚动错位”问题的根源。
遮罩层为什么不能用 opacity 控制透明度
用 opacity: 0.6 给遮罩层设透明度,会导致它内部所有子元素(比如关闭按钮、表单输入框)也跟着变半透明——这不是你想要的视觉效果,更糟的是,它还会干扰可访问性(如屏幕阅读器读取逻辑)和事件捕获顺序。
- 正确做法是用
background: rgba(0, 0, 0, 0.6):只让背景色半透,内容完全不受影响 - IE8 及更老版本不支持
rgba,需 fallback:filter: alpha(opacity=60)(仅限 IE),但现代项目基本可忽略 - 如果遮罩里要放按钮,别忘了给按钮加
pointer-events: auto,否则点击会失效
position: fixed 和 position: absolute 怎么选
遮罩是否随页面滚动而消失,直接决定定位方式。错用会导致遮罩“飘走”或只盖住局部。
- 全屏遮罩(如登录弹窗、加载提示)→ 必须用
position: fixed,并配top: 0; right: 0; bottom: 0; left: 0 - 容器内遮罩(如某个卡片的操作锁定)→ 用
position: absolute,但其父容器必须有position: relative,否则遮罩会相对于body定位,大概率错位 - 不要对遮罩或其任意祖先加
transform、will-change或overflow: hidden,否则 Safari 会直接禁用backdrop-filter
弹层被遮罩盖住?检查这三处 z-index
遮罩和弹层的层级关系不是“谁大谁在上”那么简单,而是必须形成明确的堆叠上下文(stacking context)。
- 遮罩层
z-index设为999,弹层必须显式大于它,比如z-index: 1000,不能依赖默认值 - 弹层父容器若用了
transform、opacity 、<code>filter等属性,会创建新堆叠上下文,导致弹层实际层级被“重置”,此时再大的z-index也无效 - 移动端 iOS Safari 在遮罩移除瞬间容易发生点击穿透,稳妥做法是:先设
pointer-events: none,再用setTimeout(() => { /* 移除 DOM */ }, 0)推迟到下一轮事件循环
真正难的不是写出能动的遮罩,而是每次 DOM 结构微调、CSS 新增一个 transform、甚至引入第三方 UI 库时,都要重新验证遮罩与弹层的层级是否依然成立——这种隐式依赖最容易在迭代中被遗忘。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











