状态栏遮挡本质是页面未顶起,App端需启用沉浸式并动态垫高;H5用env(safe-area-inset-top),小程序用custom导航+胶囊计算;WebView需plus API重设top。

状态栏内容被遮挡,本质是页面没“顶上去”
uni-app 去掉 titleNView 后,页面默认仍从状态栏下方开始渲染,导致顶部内容被系统状态栏(时间、信号、电池)盖住。这不是样式写错了,而是布局起点没对齐——页面容器的 top 起点仍是屏幕顶部,但内容区域却被“下压”了。
App 端必须启用沉浸式 + 动态垫高
在 pages.json 对应页面中,app-plus 节点需同时配置两项:
-
"titleNView": false—— 关闭原生导航栏 -
"statusbar": {"immersed": true}—— 启用沉浸式(让页面内容可延伸至状态栏区域)
仅设 immersed: true 不够:此时内容虽能顶到屏幕最上,但文字会直接叠在状态栏上。必须配合 CSS 垫高:
.navbar {
padding-top: var(--status-bar-height);
}
注意:--status-bar-height 在 App 端返回的是真实像素值(如 44px),无需手动调用 uni.getSystemInfo;但若使用 nvue,则需用 uni.getSystemInfoSync().statusBarHeight 动态赋值。
H5 和小程序端不能依赖 --status-bar-height
--status-bar-height 在 H5 端恒为 0,小程序端固定为 25px,无法反映 iPhone X+ 的实际刘海高度。所以跨端时:
- H5:靠
<meta name="viewport" content="viewport-fit=cover">+env(safe-area-inset-top)实现安全区适配 - 微信小程序:优先用
navigationStyle: "custom",再通过uni.getMenuButtonBoundingClientRect()计算胶囊位置,推导出实际可用顶部空间 - 两者都不要硬写
padding-top: 25px,否则在安卓机或新 iOS 上会留白过多
WebView 组件会强行覆盖状态栏,必须手动重设 top
当页面含 <web-view></web-view> 时,它默认全屏且层级最高,会把状态栏也盖住。解决方式不是改 z-index,而是用 plus API 动态调整其位置:
const webview = this.$scope.$getAppWebview().children()[0];
webview.setStyle({
top: uni.getSystemInfoSync().statusBarHeight,
height: 'calc(100% - ' + uni.getSystemInfoSync().statusBarHeight + 'px)'
});
这个操作必须放在 onReady 或带 setTimeout 的 onLoad 中执行,否则 children()[0] 可能为空——WebView 渲染晚于 Vue 生命周期。
真正容易被忽略的是:不同平台的“状态栏”概念不统一。App 端是系统级区域,H5 是浏览器视口约束,小程序是逻辑安全区。一套 CSS 变量撑不起全端,得按平台特性分治。


















