viewport-fit=cover是安全区适配的硬性开关,必须与width=device-width同时使用,否则env(safe-area-inset-bottom)恒为0px;需同时声明constant()和env()且前者在前,fixed元素避让必须用padding而非margin。

viewport-fit=cover 是安全区适配的硬性开关,不加它,env(safe-area-inset-bottom) 永远是 0px,所有 CSS 适配都白写。
viewport-fit=cover 必须和 width=device-width 同时存在
单独写 viewport-fit=cover 不起作用。浏览器会忽略它,或回退到默认的 auto(等价于 contain)。原因在于:layout viewport 宽度没被正确设为设备逻辑像素宽度,viewport-fit 就失去作用基础。
-
width=device-width强制 layout viewport 等于屏幕逻辑宽度(如 iPhone 12 是428px),这是后续所有缩放、适配的前提 -
initial-scale=1.0必须搭配width=device-width才能生效;否则在多数安卓 WebView 中会被静默忽略 - 避免混用已废弃的
target-densitydpi,它会直接让浏览器跳过viewport-fit - 如果禁用缩放,保留
maximum-scale=1.0,某些旧版 WebView 依赖它来确认“cover 模式可用”
为什么只写 env() 或 constant() 都会漏兼容
iOS 11.0–11.1 只识别 constant(),iOS 11.2+ 及现代 Chrome/Safari 只认 env()。两者必须共存,且顺序不能错——constant() 在前,env() 在后。
- 错误写法:
padding-bottom: env(safe-area-inset-bottom)→ iOS 11.0–11.1 下返回0px,底部按钮被小黑条遮住 - 错误写法:
padding-bottom: constant(safe-area-inset-bottom)→ iOS 12+ 和 Android Chrome 直接忽略该声明 - 正确写法(两条独立声明):
padding-bottom: constant(safe-area-inset-bottom, 0px);padding-bottom: env(safe-area-inset-bottom, 0px); - 不能合并成一条:
padding-bottom: constant(...) env(...)是非法 CSS,解析失败
fixed 元素底部避让必须用 padding,不是 margin
给 fixed 定位的 tabbar 或操作栏加 margin-bottom 看似合理,但实际无效——margin 不撑开父容器,内容仍可能溢出到非安全区;只有 padding 能真正预留可显示空间。
立即学习“前端免费学习笔记(深入)”;
- 对吸底元素本身设
padding-bottom,而非对其父容器设margin-bottom - 顶部适配同理:对
<body>或根容器设padding-top: constant(safe-area-inset-top, 0px); padding-top: env(safe-area-inset-top, 0px); - 部分安卓 WebView 对
viewport-fit=cover支持不一致,建议用@supports (padding-top: env(safe-area-inset-top))做渐进增强 - 微信小程序内嵌 H5 中,
viewport-fit=cover在 8.0.33+ 版本才稳定生效;7.x 早期版本会静默回退到auto
最常被忽略的一点:env() 返回的是长度值(如 34px),不能直接参与 calc(100vh - env(...)) 这类计算,除非确保所有环境都支持单位运算——iOS 11.2+ 支持,但部分安卓 WebView 会报错或返回 0。稳妥做法是用 padding 单独控制留白,而非试图动态重算高度。



















