必须用 var(--status-bar-height) 做 css 占位,不能靠 js 获取高度;app 端 navigationstyle 设为 "custom" 后状态栏仍存在且透明叠加,需 padding-top: var(--status-bar-height) 占位,该变量由原生层注入、ios/android 自适应、h5 为 0,配合 background-color: transparent 等设置实现真沉浸。

必须用 var(--status-bar-height) 做 CSS 占位,不能靠 JS 获取高度
App 端 navigationStyle 设为 "custom" 后,原生导航栏被移除,但状态栏仍存在——它不是“消失”,而是变成透明层叠在页面最上方。此时若不手动占位,页面内容会直接顶进状态栏区域,首行文字被遮挡。
uni-app 在 App 端运行时会自动注入 CSS 变量 --status-bar-height,值已适配 iOS/Android 各类刘海、挖孔、全面屏机型。这个变量只在 navigationStyle: "custom" 生效的页面中可用,且比调 uni.getSystemInfoSync() 更可靠:
-
uni.getSystemInfoSync().statusBarHeight在onLoad阶段常返回0或错误值(DOM 未就绪、H5/小程序环境无该字段) -
--status-bar-height是运行时由原生层注入的 CSS 变量,iOS 返回真实像素(如 47),Android 动态适配(非固定 24),无需条件判断 - 直接在样式里写
padding-top: var(--status-bar-height)即可,H5 端该变量值为0,天然兼容
自定义导航栏本身要设 background-color: transparent,且不能有 box-shadow 或 border
很多人以为设了 navigationStyle: "custom" 就自动“沉浸”,其实只是交出控制权。你写的 <view class="nav"></view> 默认是不透明块级元素,即使加了 padding-top,视觉上仍是“一块白板盖在状态栏下面”,而非“内容延伸到状态栏下方”。
关键动作是让导航栏真正“看不见”,同时保持布局空间:
-
background-color: transparent必须显式声明,不能依赖默认或 inherit - 禁用所有可能破坏透明感的属性:
box-shadow、border、opacity(会导致文字发虚,iOS 尤其明显) - 若用
<uni-nav-bar></uni-nav-bar>,它默认带背景色,需绑定:background-color="transparent" - 避免在导航栏内放
<input>或弹窗类交互,软键盘弹出会顶起整个 webview,导致内容穿透状态栏
下拉刷新时内容穿透状态栏?临时关闭透明效果
开启 "enablePullDownRefresh": true 后,整个 webview 会被原生层拖动下拉,透明导航栏下的内容就会直接滑进状态栏区域。Android 容易变黑、闪烁,iOS 可能出现文字错位——这不是样式问题,而是原生渲染层叠加顺序导致的。
别试图用 z-index 或重绘修复。正确做法是行为隔离:
- 加响应式 class,例如
class="{ 'nav-transparent': !isPulling }" - 在
onPullDownRefresh中设isPulling = true - 在
stopPullDownRefresh后设isPulling = false - CSS 中定义
.nav-transparent { background-color: transparent; },否则默认不透明
真机调试必须用正式打包的 IPA/APK,模拟器和 HBuilderX 调试基座无效
--status-bar-height 的值由原生层在窗口创建时注入,依赖系统真实的窗口 flags 设置。HBuilderX 自带的调试基座和模拟器不触发完整原生生命周期,--status-bar-height 常为 0 或渲染不准,测不出真实沉浸效果。哪怕样式全对,不打正式包就等于没验证。











