最直接可靠的方式是检查 --status-bar-height 是否为非零值;该变量由 uni-app 在 app 端注入,仅当 navigationstyle: "custom" 生效且环境支持时存在有效像素值,h5 和小程序中恒为 "0px"。

怎么用 CSS 变量判断是否启用沉浸式状态栏
最直接可靠的方式是检查 --status-bar-height 是否为非零值。这个变量由 uni-app 在 App 端运行时注入,仅当 navigationStyle: "custom" 生效且环境支持时才存在且有实际像素值(如 "44px" 或 "25px");H5 和小程序中该变量默认为 "0px"。
可在样式中快速验证:
.debug-status {
/* 若生效,会显示具体高度;否则不显示 */
content: 'status-bar-height: ' attr(style);
}
@media (prefers-reduced-motion: reduce) {
/* 非必要不触发 JS 判断,优先用 CSS 变量 */
}
- 在页面根元素上加
style="height: calc(var(--status-bar-height) + 100vh)",真机调试时若页面明显“下移”,说明变量已生效 - 不要依赖
uni.getSystemInfoSync().statusBarHeight判断——它在 H5/小程序里可能返回0或undefined,且在onLoad阶段常为0,无法反映真实渲染状态 - 如果
getComputedStyle(document.documentElement).getPropertyValue('--status-bar-height')返回空字符串或"0px",基本可判定未开启 custom 模式或未走 App 端原生渲染流程
为什么不能靠 navigationStyle 配置项直接判断
pages.json 中写了 "navigationStyle": "custom" ≠ 实际启用了沉浸式效果。这个配置只是“申请权限”,是否真正生效取决于三件事:是否在 app-plus 子节点下同时设了 "titleNView": false、是否用了正式打包的 IPA/APK、以及当前运行环境是否为 App 端(uni.getProvider({service: 'system'}) 返回 app)。
- 微信小程序也支持
custom,但不支持--status-bar-height注入,CSS 变量始终为"0px" - HBuilderX 模拟器不会注入该变量,即使配置正确,
getComputedStyle也拿不到有效值 - 若
app-plus节点缺失或titleNView未显式设为false,custom 会被忽略,页面仍预留导航栏空间
JS 中安全判断的最小可行代码
需满足两个条件才认为沉浸式状态栏真正就绪:变量存在且大于 0,且运行环境为 App。
const isImmersiveReady = () => {
const heightStr = getComputedStyle(document.documentElement)
.getPropertyValue('--status-bar-height')
.trim();
const heightPx = parseFloat(heightStr) || 0;
const isApp = uni.getSystemInfoSync().platform === 'app';
return isApp && heightPx > 0;
};
- 必须在
onReady或之后调用,onLoad时机太早,DOM 和变量都可能未就绪 - 不要在
onLaunch判断——此时页面尚未加载,document不可用 - 返回
true才代表可安全使用var(--status-bar-height)布局,否则应 fallback 到固定值或隐藏相关 UI
容易被忽略的真机验证环节
所有判断逻辑在 HBuilderX 模拟器或网页预览中均不可信。只有安装正式打包的 IPA/APK 后,--status-bar-height 才会被正确注入并参与渲染。iOS 和 Android 行为也不一致:Android 部分全面屏机型会动态调整该值(如横屏时归零),而 iOS 一旦注入即固定。
- 测试时务必关闭「调试基座」,启用「自定义调试基座」或直接打包安装
- 横屏场景下,部分 Android 设备会重置
--status-bar-height为"0px",需监听resize事件重新判断 - 若用户手动开启系统「简易模式」或「高对比度」,该变量可能失效,应有降级样式兜底











