所有尺寸一律用rpx,禁用px和vh/vw;字号优先用upx;安全区适配iOS用env/constant,Android需配置navigationStyle;scroll-view回弹与滚动条需分端控制;video组件在App端层级最高,需用nvue或外置按钮。

用 rpx + 条件编译,别碰 px 和 vh/vw
直接写 px 或 vh 是 iOS/Android 样式错位的头号原因。rpx 虽然统一换算基准(750rpx = 屏幕宽),但 Android WebView 和 iOS WKWebView 对 rpx 的像素映射精度存在细微偏差,尤其在字体、边框、小尺寸间距上更明显;而 vh 在小程序和 App 端计算逻辑不一致——iOS 按视口高度算,Android 可能含状态栏,H5 又按浏览器窗口,三端结果经常差 20–40px。
- 所有尺寸(
padding、margin、font-size、height)一律用rpx,禁用px和vh/vw - 字号优先用
upx(uni-app 封装单位,比 rpx 更稳,对字体缩放做了额外校准) - 必须用
vh的场景(如全屏背景),只在H5下启用:/* #ifdef H5 */ height: 100vh; /* #endif */
安全区适配:iOS 底部黑条和 Android 导航栏不是同一个问题
iOS 底部“黑条”本质是安全区(safe-area-inset-bottom),而 Android 的导航栏变色/高度浮动是系统 UI 控制逻辑不同,混为一谈会导致两边都修不好。
- iOS:用 CSS
env(safe-area-inset-bottom)+constant(safe-area-inset-bottom)双兜底,写在固定定位元素上,例如:.fixed-bottom { padding-bottom: env(safe-area-inset-bottom); padding-bottom: constant(safe-area-inset-bottom); } - Android:不能靠 CSS,得改
manifest.json中的app-plus配置项,设置"navigationStyle": "custom"并手动控制状态栏/导航栏颜色,否则部分厂商(如小米、华为)会强制显示半透明导航栏,遮挡内容 - 千万别在 iOS 上用
padding-bottom: 34px这类写死值——iPhone 15 Pro Max 和 iPhone SE 的安全区高度差近一倍
scroll-view 回弹和滚动条:iOS 弹、Android 显,得分开关
scroll-view 在 iOS 默认开启弹性回弹(bounce),在 Android 默认显示滚动条,两者行为互不干扰,但同一套属性在两端效果相反。
- iOS 要禁用回弹:加属性
bounce="false"(注意不是enable-bounce,那是旧版写法) - Android 要隐藏滚动条:加样式
::-webkit-scrollbar { display: none; },且必须放在/* #ifdef APP-PLUS */块里,H5 和小程序不认这个伪类 - 如果用了
scroll-y但内容高度不足,iOS 仍可能触发回弹——得配合scroll-top手动重置或监听scrolltoupper事件做防御性处理
video 组件层级:H5 可盖、App 端永远在最上
这是最容易被忽略的“视觉幻觉”问题:H5 里 z-index 能把按钮盖在 上,但 App 端(iOS/Android)的原生视频播放器渲染在独立图层,所有 WebView 内的 DOM 元素默认都在它下面。
- 真机调试时发现按钮消失,先确认是不是
video组件——不是 bug,是平台限制 - 方案一(推荐):改用
nvue页面写 video,nvue 支持原生层级控制,可让自定义控件与视频同层 - 方案二:放弃覆盖,把控制按钮挪到
video外部容器里,用position: absolute+top/bottom定位,避开视频原生区域 - 千万别在 App 端尝试
transform: translateZ(999)或will-change强升层级——无效
实际项目里最麻烦的从来不是单个平台修不修得好,而是改了 iOS 的安全区,Android 的导航栏又飘了;关了 scroll-view 回弹,H5 端滚动惯性也跟着没了。条件编译不是偷懒手段,是把平台差异显式暴露出来、逐个击破的必要过程。











