uni.getsysteminfosync().safeareainsets 是最直接获取安全区偏移的方式,返回含 top、bottom、left、right 的 px 对象,需用可选链兜底且配合 css env() 兼容多端。

uni.getSystemInfoSync().safeAreaInsets 是最直接的获取方式
它返回一个对象,含 top、bottom、left、right 四个字段,单位是 px(不是 rpx),代表当前设备系统计算出的安全区偏移量。这个值在 iOS App 真机上最稳定;微信小程序需基础库 ≥ 2.10.4 且必须在 onShow 或 onReady 后调用才可靠;H5 和支付宝小程序该字段始终为 undefined 或空对象。
常见错误现象:onLoad 里就调用却取不到 safeAreaInsets,或没做空值判断直接解构导致报错 Cannot destructure property 'bottom' of 'undefined'。
- 务必用可选链操作符:
systemInfo.safeAreaInsets?.bottom || 0 - 不要在
data()初始化时硬设默认值(如bottomPadding: 34),应初始化为0或null,等生命周期钩子中再赋值 - Android 全面屏机型(如华为 Mate 系列、小米部分新机)也可能返回该字段,但不保证所有厂商都透出,不能当作 Android 通用方案依赖
为什么不能只靠 JS 获取,还得配合 CSS 的 env()?
因为 safeAreaInsets 在 H5 和部分小程序环境根本不存在,而 env(safe-area-inset-bottom) 是 Web 标准原生能力,在支持全面屏的 iOS WebView 和较新安卓 WebView 中能直接生效,且无需 JS 干预、无时机问题。
常见错误现象:只写 JS 动态设置 padding-bottom,结果 H5 页面底部按钮被浏览器地址栏遮挡;或只写 env() 却没 fallback,导致旧版微信白屏。
- 必须同时写两行兼容 iOS 11.0+:
padding-bottom: constant(safe-area-inset-bottom);和padding-bottom: env(safe-area-inset-bottom); - 加在内容容器上(如
.page-body),别加在<page></page>根节点,否则可能撑开整个滚动区域 - 若需 JS 控制逻辑(如横竖屏切换后重算),仍要读
safeAreaInsets.bottom,但仅作辅助判断,样式层仍以env()为主
uni.getWindowInfo() 和 uni.getSystemInfoSync() 有什么区别?
uni.getWindowInfo() 返回的是当前窗口的实时渲染信息,其中也含 safeAreaInsets 和 safeArea 字段;而 uni.getSystemInfoSync() 返回的是设备级静态系统信息(含型号、品牌、平台等)。两者字段名一致,但来源和稳定性不同。
常见错误现象:误以为 uni.getWindowInfo() 更“新”就一定更准,结果在 H5 或某些小程序里发现它也返回 undefined;或在 onLoad 就调用,窗口尚未 layout 完成,safeArea 高度为 0。
-
uni.getWindowInfo()在 App 端支持更好,尤其适合监听窗口 resize 后重取(如视频全屏退出) -
uni.getSystemInfoSync()更轻量、无异步、首次加载即可用,适合初始化布局 - 二者都需兜底:
const bottom = info.safeAreaInsets?.bottom ?? info.safeArea?.bottom ?? 0
动态适配时最容易忽略的三个细节
安全区不是“加个 padding 就完事”的简单问题,漏掉任一环节都会导致真机白条、按钮遮挡或留白异常。
- 单位混淆:
safeAreaInsets是 px,但页面样式常用 rpx —— 若需 JS 计算后绑定到 style,记得用uni.upx2px()转换,否则在不同屏幕宽度下会失真 - 底部指示条高度是动态的:iPhone 14 Pro 横屏时
safe-area-inset-bottom是 0,竖屏才是 34;XR/11 是 34,但 mini 机型可能只有 28 —— 不能硬编码 - 背景色要延伸到底部:即使 padding 加对了,如果容器背景色没覆盖到底部安全区,仍会露出白条或系统色块,需确保父容器或 body 设置了统一背景











