遮罩层错位因父容器触发新包含块,应挂载到body、用inset:0;z-index失效因层叠上下文隔离,需确保遮罩z-index高于其最近层叠祖先;响应式下优先100vw+overflow:hidden;移动端需touch-action:none防点击穿透。

遮罩层用 position: fixed 为什么经常“错位”或“不覆盖全屏”
因为 fixed 是相对于视口定位,但若父容器有 transform、perspective 或 filter(哪怕只是 transform: translateZ(0)),浏览器会创建新的包含块,导致 fixed 元素相对该容器而非视口定位——这是最常被忽略的根源。
实操建议:
- 检查遮罩层所有祖先元素,用 DevTools 的“Computed”面板搜
transform、filter、perspective,有就干掉或换方案 - 遮罩层尽量挂到
下,绕过中间容器干扰 - 别依赖
top: 0; left: 0; width: 100%; height: 100%,改用inset: 0(兼容性够用时)更可靠
z-index 层级失效:遮罩层被内容盖住怎么办
z-index 不是全局排序,它只在同一个层叠上下文(stacking context)内生效。一旦某个父容器设置了 position + z-index(且值不为 auto),它就创建了新层叠上下文,子元素的 z-index 只能在这个小圈子里比高低。
常见错误现象:modal 里套了 z-index: 9999 的遮罩,但外层有个 header 设置了 z-index: 100 且触发了层叠上下文,结果遮罩永远压不住 header。
立即学习“前端免费学习笔记(深入)”;
实操建议:
- 用 DevTools 的“Layers”面板或勾选“Show layer borders”,看遮罩和目标元素是否在同个层叠上下文
- 遮罩层的
z-index必须高于其最近的、有层叠上下文的祖先的z-index值(不是子孙) - 如果无法控制外层组件,直接把遮罩层用
document.body.append()动态插入,确保它在顶层上下文
响应式下遮罩层尺寸不准:width: 100vw 和 100% 怎么选
100% 是相对父容器宽度,100vw 是相对视口宽度。滚动条存在时,100vw 包含滚动条宽度(比如 17px),而 100% 不包含——这会导致遮罩右侧多出一条白边或内容被遮一半。
使用场景:
- 需要严丝合缝盖住整个可视区域(包括滚动条位置),用
inset: 0或width: 100vw; height: 100vh,但要加overflow: hidden防滚动条抖动 - 遮罩只用于局部弹窗(如卡片内 modal),用
100%更稳妥 - 移动端 Safari 对
vh有兼容问题(地址栏缩放时高度突变),此时优先用100%+min-height: 100vh
移动端点击穿透:遮罩层下元素被误触
本质是 iOS Safari 的“延迟点击”机制:遮罩层出现后,手指还没抬起来,系统仍把下一次点击映射到原来位置。尤其当遮罩是 opacity: 0 或 visibility: hidden 时,根本没拦住事件流。
实操建议:
- 遮罩层必须有
pointer-events: auto(默认值),且不能是none - 禁用穿透最稳方案:遮罩层加
touch-action: none,同时 body 加overflow: hidden - 避免用
opacity: 0控制显隐,改用visibility: hidden+opacity: 0组合,或直接display: none
真正麻烦的从来不是写几行 CSS,而是你得同时盯着视口行为、层叠上下文链、移动端事件模型和滚动条存在感——这些地方一碰就出事,而且不出错则已,一出就是线上用户点不到按钮。


















