必须删除 pages.json 中整个 tabBar 对象(含 list、color 等所有字段),否则 uni-app 会保留 50px 不可见占位层,导致自定义 tabBar 被顶高、毛玻璃效果错位、safe-area 计算异常;凸起按钮须用 fixed + absolute 组合定位,背景模糊需渐进增强并绕开 WebView 兼容坑,状态与跳转必须手动接管。

custom: true 必须删干净 pages.json 的 tabBar 块
不删掉整个 tabBar 对象(包括 list、color、backgroundColor 等所有字段),哪怕只留一个空对象或注释不全,uni-app 仍会悄悄保留一个 50px 高的不可见占位层。这会导致你后续加的毛玻璃效果被顶高、底部内容被截断、env(safe-area-inset-bottom) 计算错乱。
常见错误现象:custom-tab-bar/index.vue 渲染出来了,但背景模糊区域总有一段“看不见的空白”,或者 iOS 上模糊边缘被圆角裁切一半。
- 打开
pages.json,搜索"tabBar",整块删除(不是注释,是物理删除) - HBuilderX 不报错,静默失败是常态;删之前建议备份原配置
- 确认删除后重启 H5 或真机预览,用 Chrome DevTools 检查 body 底部是否还有残留 padding/margin
用 backdrop-filter 实现毛玻璃,但得绕开 WebView 兼容坑
backdrop-filter: blur(10px) 在 iOS Safari 和微信小程序基础库 2.27+ 支持良好,但 Android WebView(尤其旧版 UC、QQ 浏览器内核)基本不支持,直接写死会白屏或降级为纯色。
正确做法是渐进增强:
- 先设默认背景:
background-color: rgba(255, 255, 255, 0.8) - 再叠加毛玻璃:
backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px) - 加
border-top: 1rpx solid rgba(0,0,0,0.05)弥补模糊导致的边界发虚 - 避免在
scroll-view内部嵌套该容器——部分安卓机型 scroll 时 backdrop 会闪烁或失效
别用 filter: blur() 作用于父容器,那会把内部按钮、图标一起糊掉。
凸起按钮 + 模糊背景的定位必须用 fixed + absolute 组合
想让中间那个“+”按钮浮在模糊背景之上且居中,靠 margin-top、transform: translateY() 或 flex 布局,在滚动/键盘弹出/安全区变化时极易偏移,真机上常出现按钮随页面一起动、甚至消失。
可靠写法:
- 外层容器:
position: fixed; bottom: 0; left: 0; right: 0; padding-bottom: env(safe-area-inset-bottom, 34px); z-index: 999 - 模糊背景层:
position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.8); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px) - 凸起按钮:
position: absolute; bottom: 20px; left: 50%; transform: translateX(-50%); z-index: 1000 - 鸿蒙端
env(safe-area-inset-bottom)可能返回 0,fallback 到34px更稳
状态同步和跳转必须手动接管,uni.switchTab 会静默失败
启用 custom: true 后,uni.switchTab() 对未出现在原 tabBar.list 中的页面(你已删了)会直接忽略,不报错也不跳转。凸起按钮点击也收不到 uni.onTabItemTap。
必须自己处理:
- 当前激活页用
data或 Pinia 存,不要依赖uni.getTabBar()(H5 返回undefined) - 每个 tab 项点击时,用
uni.getPages().find()查栈,存在则uni.navigateTo(),否则uni.reLaunch() - 凸起按钮单独绑定
@click,走自定义逻辑(如弹窗、发布页等),不走 tab 切换流 - 页面 onShow 里手动同步选中态:
this.selectedIndex = this.tabList.findIndex(i => i.pagePath === getCurrentPages().pop().route)
最易被忽略的是:iOS 安全区高度动态变化(比如从横屏切回竖屏),此时仅靠 CSS 的 env(safe-area-inset-bottom) 不够,需要监听 resize 事件重算 padding-bottom 并触发视图更新。











