移动端全屏搜索遮罩用 position: fixed 而非 absolute,因其必须锚定视口、不随滚动偏移;absolute 受祖先 overflow/transform 限制易覆盖不全,且 fixed 在祖先含 transform 等属性时会降级定位,故应直挂 body 并动态设 height 防 iOS Safari 漏底。

移动端全屏搜索遮罩为什么用 position: fixed 而不是 absolute
因为搜索遮罩必须始终覆盖整个可视区域,且不随页面滚动偏移。用 absolute 会相对于最近的已定位祖先(比如某个 section 或 div)定位,一旦该祖先有 overflow: hidden、transform 或高度限制,遮罩就盖不全,甚至消失在视口外。
而 fixed 天然锚定视口,滚动时稳如磐石——但前提是它没被父容器“劫持”:只要任意祖先元素设置了 transform、filter、perspective 或 will-change,就会创建新包含块,让 fixed 相对它而非视口定位。这是 iOS 和部分 Android WebView 中遮罩错位的头号原因。
- 检查所有祖先节点,用 DevTools 的 “Computed” 面板搜
transform和filter,有就删或绕开 - 最稳妥做法:把遮罩 DOM 直接挂到
document.body下,彻底避开中间容器干扰 - 别依赖
top: 0; left: 0;就万事大吉——必须显式撑满
为什么 100vh 在 iOS Safari 上会漏底
100vh 在 iOS Safari(尤其是 iOS 14–16)中会把地址栏高度算进视口,但 fixed 元素渲染时不响应地址栏收起/展开,导致遮罩高度小于实际可视区,底部露出内容。这不是写法错误,是浏览器行为缺陷。
别迷信 100svh 或 100dvh:前者 Safari 支持极差(iOS 16.4+ 实验性),后者完全不支持;100% 更危险,它参考的是父容器高度,而 fixed 元素的父级是 viewport,% 在此场景下无效。
- 生产环境首选 JS 动态设置:
overlay.style.height = window.innerHeight + 'px' - 配合
window.addEventListener('resize', () => {...})监听横竖屏切换和地址栏变化 - 同时给
加style="overflow: hidden"锁定滚动,防穿透
z-index 层级失效的三个真实场景
遮罩明明写了 z-index: 9999 却被 header 或弹窗按钮压住?大概率掉进了层叠上下文陷阱。z-index 不是全局排序,只在同一个层叠上下文内有效。
常见触发点:
- 外层
header设置了position: relative; z-index: 100→ 它创建了新层叠上下文,你遮罩的z-index: 9999只在这个小圈子里比高低 - 遮罩父容器加了
opacity: 0.99或transform: translateZ(0)→ 同样创建隔离上下文 - 遮罩和目标元素不在同一 DOM 树层级(比如遮罩在
#app内,而 header 是兄弟节点)→ 浏览器按 HTML 顺序决定初始堆叠顺序
实操建议:
- 用 DevTools 的 “Layers” 面板确认遮罩和被盖元素是否同属一个 stacking context
- 遮罩设
z-index: 1000,搜索框本体设z-index: 1001,差值不用大,但必须严格递进 - 避免魔数,统一用 CSS 变量:
--z-search-overlay: 1000
点击遮罩没反应?先查这三件事
遮罩点了没关闭、点背后按钮却触发了——说明事件流没控住。这不是逻辑问题,是基础属性缺失。
- 遮罩必须有
background-color(哪怕rgba(0,0,0,0.01)),完全透明时部分 Safari 视为“不可点击” - 确保没写
pointer-events: none;如果写了,就改回pointer-events: auto(默认值) - 加
cursor: pointer,Safari 对无 cursor 的fixed元素 click 事件支持不稳定 - JS 监听时用
event.target === event.currentTarget判断是否点在遮罩本体上,防止点到内部输入框误关
真正麻烦的从来不是怎么铺满全屏,而是当页面用了 scroll-behavior: smooth 或嵌套了第三方组件(比如地图、视频)时,它们悄悄创建的合成层会让所有 z-index 和定位规则突然失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











