viewport-fit=cover 是灵动岛适配的必要前提,需与 width=device-width 共存于 viewport meta 标签中;配合 env(safe-area-inset-top) 避开顶部安全区,底部需通过 ua 和媒体查询识别机型并手动预留 15px 空间。

Viewport-fit=cover 是灵动岛适配的必要前提
不加 viewport-fit=cover,网页默认会被 iOS 系统强制“安全区裁剪”——灵动岛区域直接变黑或留白,内容永远无法延伸进去。这个值不是可选,是开启异形屏适配的开关。
它必须写在 <meta name="viewport"> 的 content 属性里,且需与 width=device-width 等基础参数共存:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
-
viewport-fit=cover不会自动把内容塞进灵动岛,只是“允许”页面渲染到屏幕边缘 - 仅 Safari on iOS 15+ 支持;Android Chrome 忽略该参数,无副作用
- 如果同时用了
maximum-scale=1.0或user-scalable=no,可能干扰 pinch-zoom 行为,但不影响灵动岛渲染
用 env() 函数读取安全区边距适配灵动岛顶部
有了 viewport-fit=cover,页面能铺满全屏,但顶部状态栏下方、灵动岛正上方那块区域(即「齐刘海+灵动岛」组合安全区)仍需主动避开,否则文字/按钮被遮挡。iOS 提供了 CSS 环境变量 env(safe-area-inset-top) 来获取这个动态高度。
典型用法是给 或首层容器加 padding:
body {<br> padding-top: env(safe-area-inset-top);<br>}
-
env(safe-area-inset-top)在 iPhone 14 Pro 及更新机型上,灵动岛激活时返回约59px(含状态栏 44px + 灵动岛额外 15px),未激活时回落为44px - 不要用
constant()—— 已被弃用,Safari 16.4+ 完全不识别 - 该值不能用于 JS 的
getComputedStyle直接读取(返回空字符串),只能在 CSS 中作为长度单位使用
灵动岛下方区域需要手动预留空间
顶部有 safe-area-inset-top,但底部灵动岛本身不触发 safe-area-inset-bottom(该值始终为 34px,对应常规 Home Indicator 高度)。也就是说:系统不认为灵动岛底部是“需避让”的安全区,但实际它会悬浮在屏幕最下方、覆盖内容。
目前唯一可靠方案是通过 UA 检测 + 媒体查询做设备级判断:
- 检测
navigator.userAgent是否含iPhone OS 16_*且设备宽度为390px或430px(iPhone 14 Pro/Pro Max 屏宽) - 配合
@media (device-height: 844px) or (device-height: 932px)进一步过滤 - 满足条件时,对底部固定元素(如 tabbar)加
padding-bottom: 34px并额外增加margin-bottom: 15px(灵动岛悬浮高度)
没有通用 CSS 环境变量能反映灵动岛是否正在活跃,JS 也无法监听其展开/收起状态。
避免用 fixed 元素覆盖灵动岛区域
很多页面用 position: fixed; bottom: 0 实现底部导航栏,这在灵动岛机型上会直接被盖住——因为 fixed 元素默认无视安全区,且 safe-area-inset-bottom 不包含灵动岛高度。
- 改用
position: fixed; bottom: env(safe-area-inset-bottom)只解决 Home Indicator,不解决灵动岛 - 真正稳妥的做法是:给 fixed 底部容器设置
inset: auto auto 34px auto,再用 JS 根据设备型号动态加padding-bottom: 15px - 若使用
bottom: 0+height: 80px这类硬编码,灵动岛会直接叠在上面,用户点击无效
灵动岛不是“安全区”,它是悬浮 UI 层;适配本质是承认它不可被 CSS 环境变量精确描述,只能靠设备特征 + 经验值兜底。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











