viewport-fit=cover 是启用安全区变量的硬性前提,必须与 width=device-width、initial-scale=1.0 共存,且 meta 标签中用等号;ios 11.2+ 支持 env(),旧版需 fallback constant(),并按 constant 在前、env 在后的顺序声明。

没加 viewport-fit=cover,env(safe-area-inset-bottom) 就是 0px——不是你 CSS 写错了,是浏览器压根没算安全区。
viewport-fit=cover 是硬性前提,不加就无效
iOS Safari(11.2+)和基于 WebKit 的 iOS Chrome 都只认这个值来激活安全区变量。Android 设备忽略它,但不会报错,可放心共用。关键点在于:viewport-fit=cover 必须和 width=device-width、initial-scale=1.0 同时存在,缺一不可。
-
viewport-fit=auto(默认)会把页面锁在安全区内,顶部留白、底部被 Home Indicator 挡住 - 只写
viewport-fit=cover不写width=device-width,页面仍按默认 layout viewport(980px)缩放,内容糊成一团 - 写成
viewport-fit: cover(冒号)是无效的,meta 标签里必须用等号
env() 和 constant() 必须双写,且顺序不能反
加了 viewport-fit=cover 后,页面撑满屏幕,但按钮可能被灵动岛或 Home Indicator 盖住。这时要用 env() 动态预留空间,但 iOS 11.0–11.1 只支持 constant(),11.2+ 才支持 env()。所以得同时声明,并用 calc() 回退。
- 必须先写
constant(safe-area-inset-bottom),再写env(safe-area-inset-bottom),否则旧系统 fallback 失效 - 只支持
px、em、vh等原生单位,不能用rem或自定义变量嵌套 - 示例写法:
padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom);
padding-bottom 要作用在正确容器上
不是所有元素都适合直接加 env()。常见错误是给 或全局 html 加,结果整个页面下移,顶部内容又被灵动岛遮挡。
- 最稳妥的是加在固定定位的底部操作栏(如按钮组、TabBar)的父容器上
- 全屏类组件(如视频封面、Canvas)需单独包裹一层
<div class="safe-area-wrapper">,再对其设 <code>padding-bottom - 避免在 flex 容器的
justify-content: space-between下直接用env(),容易触发 Safari 的布局重排 bug
真正容易被忽略的,是“撑满”和“避让”的先后关系:先靠 viewport-fit=cover 让浏览器知道“我要全屏”,它才开始计算安全区;再靠 env() 把关键交互区域拉回来。跳过第一步,后面全是无用功。











