结论:必须关闭原生 tabbar 并手动实现 custom-tab-bar,严格遵循三步配置、凸起按钮四条件定位、分层处理 backdrop-filter、动态同步状态与高度;否则跨端模糊失效、按钮错位或页面被顶穿。

直接说结论:不能只加 backdrop-filter 就完事,必须关原生 tabBar、手动实现整套 custom-tab-bar,并在 iOS/Android/H5 三端分别处理安全区、滚动遮挡、状态同步和模糊层级——否则要么模糊失效,要么凸起按钮错位,要么页面被顶穿。
custom-tab-bar 必须启用且路径严格固定
uni-app 的 custom-tab-bar 是唯一跨端可行的方案,其他“局部覆盖”或“伪凸起”在真机上必然出问题。关键动作只有三步:
- 在
pages.json的tabBar节点下写"custom": true,否则组件根本不加载 - 根目录下必须存在
components/custom-tab-bar/index.vue,文件名和路径一个字母都不能错 - 所有 tab 页面的
page.json中加"disableScroll": true,否则 iOS 下页面滚动时会把自定义 tabBar 顶上去
凸起按钮的定位和层级容易错乱
中间按钮不是“加个 transform: translateY(-20px)”就完事。它必须同时满足四个条件才能稳定居中、不被截断、不遮挡内容:
- 用
position: fixed+bottom定位,而不是 flex 布局里塞进去(后者在 H5 端易塌陷) -
z-index至少设为999,否则在某些 Android 机型上会被系统导航栏盖住 - iOS 需补
padding-bottom: env(safe-area-inset-bottom),否则凸起按钮底部被刘海/Home Indicator 切掉 - 按钮本身宽高要显式设置,比如
width: 100rpx; height: 100rpx;,不能靠内容撑开
背景模糊不能只靠 backdrop-filter
backdrop-filter: blur(10px) 在 H5 和部分小程序基础库中支持不全,且 uni-app 的原生 tabBar 模糊是独立机制,和自定义组件不互通。正确做法是分两层处理:
- TabBar 容器层:设
background-color: rgba(255, 255, 255, 0.32)+backdrop-filter: blur(10px),但必须确保父容器有透出内容(即页面内容得延伸到 tabBar 区域下方) - 页面底部占位:在每个 tab 页面的最外层
<view></view>加 classu-blur-effect-inset,并动态注入高度值(通过uni.getSystemInfoSync().windowBottom获取 tabBar 实际高度) - 禁止给 tabBar 设置纯色
backgroundColor,否则模糊完全不可见
状态同步和跳转逻辑必须手动维护
自定义 tabBar 没有自动激活态,uni.getTabBar() 在 H5 和部分 App 场景下返回 undefined,别信它。可靠方式只有一种:
- 在
computed中用getCurrentPages()取当前页面路径:const path = getCurrentPages()[getCurrentPages().length - 1].route - 对比
list数组里的pagePath,用findIndex得到 current 值 - 中间按钮若跳转非 tabBar 页面(如发布页),
list里对应项的pagePath留空,用单独的<view class="add-btn"></view>覆盖,点击后调用uni.navigateTo()而非uni.switchTab()
最常被忽略的是:模糊效果开启后,页面高度实际增加了,但很多开发者只改了 tabBar 样式,没同步调整页面底部 padding 或 margin,结果内容被模糊层盖住——这个高度差在不同机型上波动很大,必须用 windowBottom 动态读取,不能写死。











