viewport-fit=cover 是安全区适配的启动开关,必须在meta标签中声明,配合env()函数及fallback值动态适配各方向安全区,不可硬编码或依赖constant()。

viewport-fit=cover 是安全区适配的启动开关
不加 viewport-fit=cover,后续所有 CSS 安全区适配都无效。iOS 11+ 和 Android Chrome 69+ 支持该属性,但默认是 viewport-fit=contain,即强制将整个页面“装进”安全矩形内,顶部刘海/底部 Home Indicator 区域留白——这正是导航栏被“咬掉一块”的根源。
必须在 中明确声明:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
-
viewport-fit=cover告诉浏览器:允许内容渲染到物理屏幕边缘,别自动裁剪 - 仅设此值还不够,它只是“开闸”,真正控制内容落点靠的是 CSS 的
env() - 不要混用
user-scalable=no或maximum-scale=1.0,它们会破坏可访问性,且与viewport-fit=cover无直接关系
用 env(safe-area-inset-*) 替代已废弃的 constant()
constant() 在 iOS 14.5+ 和大多数现代 Android 浏览器中已被弃用,继续使用会导致 padding 计算为 0,内容直接撞进刘海区。必须改用 env() 函数,并提供 fallback 值。
典型写法(以顶部和左右边距为例):
.header {<br> padding-top: env(safe-area-inset-top, 12px);<br> padding-left: env(safe-area-inset-left, 16px);<br> padding-right: env(safe-area-inset-right, 16px);<br>}
-
env(safe-area-inset-top, 12px)表示:取系统提供的顶部安全距离,若不可用则退回到12px - 四个变量始终可用:
safe-area-inset-top、safe-area-inset-bottom、safe-area-inset-left、safe-area-inset-right - 不要只加
top和bottom——横屏时,原本的左右边可能变成上下边,env()会自动响应方向变化
安全区不是“固定像素值”,而是动态边界
安全区尺寸随设备型号、系统版本、屏幕方向甚至字体缩放设置实时变化。iPhone 15 Pro 横屏时,safe-area-inset-top 可能是 0,而 safe-area-inset-left 突然变成 48px(因灵动岛转到左侧)。硬编码如 padding-top: 44px 必然失效。
- 所有涉及安全区的布局,必须用
env()+ fallback,不能依赖设计稿标注的“刘海高 44px” - 圆角区域虽无独立
env()变量,但实际影响较小;真正要防的是顶部传感器区和底部 Home Indicator 区 - 测试时务必旋转真机——模拟器常忽略方向切换后的 inset 变化
底部安全区容易被忽略,尤其在 fixed 定位场景
很多开发者只处理顶部,结果底部 tab 栏或悬浮按钮被 iPhone 的 Home Indicator 遮住。问题不在按钮本身,而在其父容器未预留底部空间。
正确做法是给 body 或最外层容器加 bottom padding:
body {<br> padding-bottom: env(safe-area-inset-bottom, 16px);<br>}
- 如果使用
position: fixed的底部导航,需额外确保其bottom值大于env(safe-area-inset-bottom),例如:bottom: env(safe-area-inset-bottom, 16px); - 不要试图用 JavaScript 动态读取
screen.height - window.innerHeight来计算——这个差值不稳定,且无法反映横屏时的左右 inset - Android 挖孔屏目前对
safe-area-inset-bottom支持有限,但 fallback 值仍能保证基础可用性
安全区适配真正的难点不在语法,而在于接受“没有绝对安全坐标”这件事——它永远是操作系统告诉你的一个建议值,而不是 CSS 能精确控制的像素边界。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











