💡 前言 :在 UniApp 项目中自定义导航栏是常见需求,但微信小程序右上角的"胶囊按钮"常常遮挡内容。H5 和 App 又没有胶囊按钮,布局容易错乱。本文带你实现一套 三端通用、像素级完美适配的自定义导航栏方案!
🔍 问题分析
胶囊遮挡的原因
在微信小程序中,右上角的胶囊按钮(包含"···"和"×")是系统固定元素。如果我们使用 navigationStyle: custom
,则需要自行适配胶囊区域,否则内容会被遮挡。
【图示:未适配前,搜索框被胶囊遮挡】
💡 跨端适配思路
平台 | 特征 | 适配策略 |
---|---|---|
微信小程序 | 存在胶囊按钮 | 动态计算导航栏高度与搜索框宽度 |
H5 | 无胶囊按钮 | 固定导航栏高度(如 88rpx) |
App | 无胶囊按钮 | 与 H5 一致 |
核心思路:
- 使用
getSystemInfoSync()
获取状态栏高度; - 使用
getMenuButtonBoundingClientRect()
获取胶囊尺寸; - 计算导航栏与搜索框宽度;
- H5/App 使用默认尺寸。
🚀 核心实现代码
1️⃣ 页面配置
json
{
"name": "home",
"style": { "navigationStyle": "custom" }
}
2️⃣ 模板结构
html
<template>
<view class="app-container">
<view class="custom-navbar">
<view :style="{ height: statusBarHeight + 'px' }"></view>
<view class="navbar-content">
<wd-search
v-model="searchValue"
:custom-style="`width:${searchWidth}`"
placeholder="搜索"
hide-cancel
disabled
@click="handleSearch"
/>
</view>
</view>
<!-- 占位符,避免被遮挡 -->
<view class="navbar-placeholder" :style="{ paddingTop: statusBarHeight + 'px' }"></view>
<view>
<!-- 页面内容 -->
</view>
</view>
</template>
3️⃣ JS 逻辑
ts
<script setup lang="ts">
const searchValue = ref("");
const statusBarHeight = ref(0);
const navBarHeight = ref(88);
const searchWidth = ref("100%");
onMounted(() => {
const sys = uni.getSystemInfoSync();
statusBarHeight.value = sys.statusBarHeight || 0;
// #ifdef MP-WEIXIN
const capsule = uni.getMenuButtonBoundingClientRect();
navBarHeight.value =
capsule.bottom - statusBarHeight.value +
(capsule.top - statusBarHeight.value);
searchWidth.value = `${capsule.left - 30}px`;
// #endif
// #ifdef H5 || APP-PLUS
searchWidth.value = "100%";
// #endif
});
function handleSearch() {
uni.showToast({ title: "搜索功能开发中", icon: "none" });
}
</script>
4️⃣ 样式(SCSS)
css
.custom-navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
background-color: var(--wot-color-bg);
}
.navbar-content {
display: flex;
align-items: center;
height: 88rpx;
padding: 0 20rpx;
}
.navbar-placeholder {
height: 88rpx;
}
✅ 使用
position: fixed
固定导航栏✅
navbar-placeholder
防止内容被遮挡✅ CSS 变量适配明暗主题
🧠 常见问题 FAQ
Q1:为什么 px 和 rpx 混用?
👉 系统 API 返回 px,但布局要自适应,用 rpx 更灵活。
Q2:胶囊按钮被遮挡?
👉 检查 z-index
,并确保搜索框宽度 menuButtonInfo.left - 边距
。
Q3:异形屏如何适配?
👉 statusBarHeight
已包含安全区域,无需额外适配。
Q4:如何添加返回按钮?
vue
<wd-icon v-if="showBack" name="arrow-left" size="20" @click="goBack" />
💻 完整示例
已在以下平台验证通过:
- ✅ 微信小程序
- ✅ H5
- ✅ App(uni-app 打包)

🔗 源码地址
📦 完整代码已开源:
👉 https://gitee.com/youlaiorg/vue-uniapp-template