viewport-fit=cover必须加,否则env(safe-area-inset-*)永远返回0px;需配合@supports检测、正确作用于头部元素,并注意第三方webview兼容性及横屏/键盘等动态场景限制。

viewport-fit=cover 必须加,否则所有适配都无效
不加这个,env(safe-area-inset-top) 永远返回 0px —— 不是写错了,是浏览器压根没启用安全区 API。iOS Safari 默认用 viewport-fit=auto(等价于 contain),把页面锁在传统安全区域内,safe-area-inset-* 变量根本不会注入。
-
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">必须出现在中,且不能被构建工具(如 Vite 插件)覆盖或删掉;检查最终 HTML 源码确认存在 - 别混用
height=device-height,它会干扰 viewport 计算,导致env()失效或视口高度异常 - 微信 WebView、QQ 浏览器等第三方壳对
viewport-fit=cover支持不稳定,真机测试不可跳过
padding-top: env(safe-area-inset-top) 加在哪?不是 body
加在 body 上容易被后续 position: fixed 导航栏覆盖或抵消;加在全局容器(如 #app 或 main)上又可能让内容整体下移,顶部状态栏区域错位。最稳妥的是直接作用于固定头部本身。
- 给导航栏元素设
padding-top: env(safe-area-inset-top),配合box-sizing: border-box - 不要用
top: env(safe-area-inset-top)——env()对top/bottom无效,旧版 Safari 会直接丢弃整条规则 - 若头部有背景色或边框,需同步检查
height是否仍符合设计,避免 padding 导致视觉增高
@supports 检测必须做,不然老设备直接失效
env(safe-area-inset-top) 在 iOS 11.2+ 才真正可用;iOS 11.0–11.1 只认 constant();Android 和桌面端完全不支持。不检测就写死,会导致老设备顶部留白消失、布局塌陷。
- 用
@supports (-webkit-touch-callout: none)判断 iOS WebKit 环境最可靠,比@supports (padding-top: env(...))更稳 - 降级顺序必须是:
padding-top: constant(safe-area-inset-top);在前,padding-top: env(safe-area-inset-top);在后 - fallback 值建议设为
20px或status-bar-height估算值(如44px),别用0
横屏、软键盘弹出时 env() 不会自动更新
iOS 的 env(safe-area-inset-top) 和 env(safe-area-inset-bottom) 只在视口尺寸变化(如旋转)时触发更新,但软键盘弹出时视口高度缩了,env() 却还维持原值——结果就是底部按钮被顶到屏幕中央,留白过大。
- CSS 无解,这是 iOS Safari 和多数 WebView 的已知限制
- 如需动态响应键盘,得监听
resize事件 + JS 强制重绘(例如切换 class 名),但注意频繁触发影响性能 - 横竖屏切换时,
safe-area-inset-left/safe-area-inset-right在 iPad Pro 横屏多任务下可能非零,不能当固定常量硬编码
viewport-fit=cover 生效、@supports 正确包裹、padding 加在合适元素上。漏掉任意一环,刘海遮挡问题就会“看起来修好了,上线后又出现”。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











