env(safe-area-inset-top) 仅在 iOS 原生 WebView(如 Safari、微信内置浏览器)中,且 viewport-fit=cover 时生效;Android WebView 和小程序完全不支持,需用 constant() 回退、JS 动态获取 safeAreaInsets.top 或 statusBarHeight 并 fallback 处理。

env(safe-area-inset-top) 在 App 和 H5 中怎么用
它只在 viewport-fit=cover 生效的前提下起作用,且仅限 iOS 原生 WebView(如 Safari、微信内置浏览器)支持;Android WebView 和所有小程序端完全不识别该变量。直接写 padding-top: env(safe-area-inset-top) 在 Android 或小程序里会 fallback 为 0,导致状态栏遮挡内容。
正确做法是:先确保 <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"> 已注入(UniApp 默认 H5 模板已含,App 端需检查 manifest.json 的 viewPortFit 配置是否为 cover);再配合 fallback 写法:
.header {
padding-top: 0;
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
}
注意顺序不能颠倒——constant 必须在 env 前,否则旧版 iOS 无法生效。
navigationStyle: "custom" 下必须手动处理顶部安全距离
启用 navigationStyle: "custom" 后,原生导航栏被移除,manifest.json 中的 safearea.top 配置自动失效,此时 env(safe-area-inset-top) 仍可用,但不可靠:nvue 页面完全不支持,部分 Android WebView 也不认。
稳妥方案是 JavaScript 动态读取并绑定:
- 在
onLaunch或页面onLoad中调用uni.getSystemInfoSync() - 取
safeAreaInsets.top(单位 px),转成 rpx 后赋给响应式变量 - 用
:style="{ paddingTop: topRpx + 'rpx' }"绑定到容器上
示例:const { top } = uni.getSystemInfoSync().safeAreaInsets; const topRpx = uni.upx2px(top);
小程序端根本不用 env(safe-area-inset-top)
微信/支付宝等小程序平台不支持 env() 或 constant() 函数,写上去等于没写。它们的安全区适配走的是原生层逻辑:只要 pages.json 里对应页面配置了 "navigationStyle": "custom",框架就会自动在顶部留出 statusBarHeight 空间(通过 safeArea 区域计算)。
但要注意:这个“自动”只对原生导航栏有效;一旦你 custom 了,就得自己补 —— 不是靠 CSS,而是靠 JS 获取 statusBarHeight(注意不是 safeAreaInsets.top,小程序里这两个值可能不同)并动态设置。
所以小程序中更推荐统一用:
const systemInfo = uni.getSystemInfoSync(); const statusBarHeight = systemInfo.statusBarHeight; // 小程序专用字段
为什么 safeAreaInsets.top 有时是 0 或异常大
常见原因有三个:
-
uni.getSystemInfoSync()在某些低端 Android 机型或调试器中返回的safeAreaInsets为空或全 0,此时应 fallback 到statusBarHeight - 未启用
navigationStyle: "custom"却又手动加了顶部 padding,会导致双倍留白(原生导航栏 + 自定义 padding) - 在 nvue 页面中,
safeAreaInsets只在plus.navigator.getStatusBarHeight()可用时才准确,否则需主动调用uni.getSystemInfo异步获取(sync版本在 nvue 中可能不准)
最保险的初始化逻辑是:先查 safeAreaInsets?.top,为 0 或 undefined 时再 fallback 到 statusBarHeight,两者都无效才设为 44(iOS 默认状态栏高度)。


















