适配刘海屏需 viewport-fit=cover + env() 安全区变量 + @supports 检测,header 先设 fallback 再覆盖,禁用内联样式和 constant(),横屏/灵动岛统一用 safe-area-inset-top。

核心是让顶部内容避开刘海区域,不是“隐藏”刘海,而是确保导航栏、标题等关键元素不被遮挡。关键在 viewport 配置 + CSS 安全区变量 + 合理降级。
第一步:必须加 viewport-fit=cover
这是所有适配的前提。没有它,safe-area-inset-top 等变量不会生效:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">- 只写
viewport-fit=cover,不要混用user-scalable=no等限制,否则可能影响部分机型手势体验 - 注意:
viewport-fit=contain或默认值下,env()返回 0,等于没适配
第二步:用 env() 给顶部留白,但必须带 @supports 检测
直接写 padding-top: env(safe-area-inset-top) 在 iOS 11.1 及更早版本会整条样式失效(不是变 0,而是被浏览器丢弃):
- 正确写法是先设 fallback,再用
@supports覆盖:
padding-top: 20px; /* iOS 11.1 及以下、Android、桌面端都走这里 */
}
@supports (padding-top: env(safe-area-inset-top)) {
header {
padding-top: env(safe-area-inset-top);
}
}
- 别写成
@supports (env(safe-area-inset-top))——语法错误,env()是函数,不能单独检测 - fallback 值建议 20px~44px,别用 0;状态栏高度估算值比纯猜更稳妥
第三步:避免常见坑点
很多问题不是没加,而是加错了位置或方式:
-
内联样式无效:React/Vue 中
style={{ paddingTop: 'env(safe-area-inset-top)' }}不起作用,JS 不解析 CSS 函数,必须写在<style>或外链 CSS 里 -
别依赖 constant():iOS 11.0–11.1 支持
constant(safe-area-inset-top),但已废弃且兼容性差,现代项目建议只用env()+@supports,旧版靠 fallback 覆盖即可 -
横屏时注意 left/right:iPad Pro 横屏多任务下
safe-area-inset-left可能非零,若页面支持横屏,顶部导航也要考虑左右安全距 -
灵动岛机型(iPhone 14 Pro 起):
safe-area-inset-top在竖屏下仍为 44px(含灵动岛高度),无需额外判断机型,统一用该变量即可
补充:辅助方案(非布局层面)
如果只是想弱化视觉存在感,可配合系统设置提升体验:
- 设纯黑/深灰壁纸,让刘海区域与屏幕边框颜色融合
- 开启深色模式,状态栏和顶部背景一致,减少割裂感
- 对第三方 App(如抖音、B站)开启「安全区域显示」(路径:设置 → 显示与亮度 → 第三方应用显示比例),强制其 UI 下移



















