必须添加 viewport-fit=cover 才能启用安全区变量,否则 env() 和 constant() 均返回 0px;需双写 padding-bottom:先 constant() 后 env(),且仅支持 px/em/vh 等原生单位。

viewport-fit=cover 是硬性前提,不加就无效
没加 viewport-fit=cover,env(safe-area-inset-bottom) 和 constant(safe-area-inset-bottom) 全是 0px——不是你写错了,是浏览器压根没算安全区。很多页面写了 padding-bottom: env(safe-area-inset-bottom) 却没反应,卡在这一步。
必须显式声明,且不能拼错、不能漏空格:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
- 安卓 Chrome 76+、iOS Safari 11.0+ 支持;旧版 WebView(如 Android 4.4)会忽略它,但不会报错
- 微信小程序 WebView 默认是
cover,但 H5 页面必须自己写 - 加了之后内容会铺满物理屏幕,顶部/底部可能被遮挡——这不是 bug,是启用安全区变量的必要代价
- 别用
contain或auto,它们不触发env()变量计算
padding-bottom 要用 env() + constant() 双写,顺序不能反
iOS 各版本对函数支持不一致:constant() 在 iOS 11.0–11.2 有效,env() 从 iOS 11.2+ 开始成为标准。只写一个,老机型或特定系统补丁下会 fallback 失败。
正确写法(顺序关键):
padding-bottom: constant(safe-area-inset-bottom);<br>padding-bottom: env(safe-area-inset-bottom);
- 浏览器按 CSS 级联顺序解析,后写的生效;
env()必须写在constant()后面 - 必须用
padding,不能用margin——margin不参与安全区计算,且会被视口裁剪 -
calc()中避免混用rpx、rem等非标准单位;只允许px、em、vh等原生单位参与运算
@supports 可做渐进增强,但别依赖它判断设备类型
部分安卓 WebView(如某些定制 ROM)对 viewport-fit 支持不稳定,@supports (padding-top: env(safe-area-inset-top)) 是较稳妥的检测方式,但仅用于降级逻辑,不能替代 viewport-fit=cover 声明。
- 它只说明当前环境支持
env(),不代表安全区值一定非零——比如横屏时safe-area-inset-bottom可能为0 - 不要用它来区分 iPhone/安卓:有些安卓机支持
env()但返回值为0,有些 iOS 模拟器反而不触发 - 更可靠的做法是:始终声明
viewport-fit=cover+ 双写padding+ 用 JS 监听resize或orientationchange动态校验值
导航栏适配要分场景,底部操作区最易踩坑
异形屏的“小黑条”(Home Indicator)只出现在底部,且高度动态变化(手势开启/关闭导航栏时不同),env(safe-area-inset-bottom) 是唯一可靠来源。硬编码 34px 或 68px 在 iPhone 15 Pro Max 或红魔 9 Pro 上必然错位。
- 固定定位的底部导航栏,必须用
padding-bottom推开内容,而不是靠bottom: 0+height拼凑 - 全屏视频、Canvas、WebGL 容器需同步应用
env(safe-area-inset-bottom)控制内边距,否则播放控件会被遮挡 - 微信内嵌 WebView 有时会忽略
env(),建议加一层 JS fallback:getComputedStyle(document.body).getPropertyValue('padding-bottom')检查是否生效
真正麻烦的从来不是写几行 CSS,而是安全区值本身会随系统设置、横竖屏切换、甚至第三方键盘弹出而实时变化——env() 提供的是动态快照,不是静态常量。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











