必须添加 viewport-fit=cover 才能启用 env() 函数;否则 safe-area-inset-* 均为 0px。需用 padding-bottom/margin-bottom 而非 bottom 位移来留出安全区,且 constant() 必须写在 env() 前以兼容旧 iOS。

必须加 viewport-fit=cover,否则 env() 全是 0px
不加这句,env(safe-area-inset-bottom) 在 iOS Safari 中永远返回 0px,哪怕设备是 iPhone 15 Pro Max。它不是可选配置,而是开关——没开就完全不生效。
常见错误是只写 <meta name="viewport" content="width=device-width, initial-scale=1">,漏掉 viewport-fit=cover。正确写法是:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
viewport-fit=cover 是唯一能激活 env() 的取值;contain 和 auto 下所有 safe-area-inset-* 都退化为 0px。
padding-bottom 或 margin-bottom 才真正“撑开”布局
只对 position: fixed; bottom: 0 的元素改 bottom 值,无法防止内容被截断——因为 bottom 只是位移,不改变父容器的盒模型高度。真正让底部留白、避免遮挡的,是作用于容器自身的 padding-bottom 或 margin-bottom。
立即学习“前端免费学习笔记(深入)”;
- 固定按钮/导航栏:给其父容器(如
footer或.tab-bar)加padding-bottom - flex 布局吸底:不能靠
margin-top: auto,得在 flex 容器上设padding-bottom - 绝对定位元素:若无法改父容器,可用
margin-bottom替代,但需确保父容器有overflow: visible
兼容写法:constant() 必须写在 env() 前面
constant(safe-area-inset-bottom) 是 iOS 11.0–11.1 的私有属性,已被废弃,但老设备仍需支持。CSS 的声明顺序决定 fallback 行为:浏览器会忽略不认识的函数,所以必须先写 constant(),再写 env()。
错误写法(env 在前,老 iOS 直接跳过整条规则):
padding-bottom: env(safe-area-inset-bottom);<br>padding-bottom: constant(safe-area-inset-bottom);
正确写法(保底生效):
padding-bottom: constant(safe-area-inset-bottom);<br>padding-bottom: env(safe-area-inset-bottom);
注意:constant() 不支持 calc() 混合运算,只建议用于纯值场景;现代项目可直接弃用,但上线前务必真机测 iOS 11.1 以下设备。
Safari 15.4 之前不支持 calc() 里混用 env()
想写 padding-bottom: calc(12px + env(safe-area-inset-bottom))?Safari 15.4 之前会静默丢弃整条 CSS 规则——既不报错,也不生效。
安全写法是拆成两条声明,利用 CSS fallback 机制:
padding-bottom: 12px;<br>padding-bottom: calc(12px + env(safe-area-inset-bottom));
另外注意:env() 不支持乘除运算,calc(env(safe-area-inset-bottom) * 2) 会被整个忽略;也不能赋值给 CSS 自定义属性,--safe-bottom: env(safe-area-inset-bottom) 无效。
最易被忽略的一点:env() 只在 CSS 层参与计算,JS 里拿不到它的值——getComputedStyle(el).paddingBottom 返回的是原始声明文本或空字符串,不是最终像素值。所有适配逻辑必须纯 CSS 实现,别试图用 JS 判断或响应。


















