uni-app 中 position: sticky 多端不兼容,小程序平台未实现,h5 需严守父容器条件;推荐 scroll-view + bindscroll 手动控制 fixed,或使用 u-sticky、list-view 的 sticky-header 等封装方案。

uni-app 里直接写 position: sticky 基本无效——不是你代码写错了,是微信/支付宝/百度小程序压根没实现这个 CSS 属性,H5 端也极易因父容器样式失效。
为什么 position: sticky 在 uni-app 多端下大概率不工作
常见错误现象:sticky 在 H5 浏览器里看着正常,真机调试时“掉下来”;iOS 微信小程序里完全没反应;安卓某些低端机型滚动卡顿甚至错位。
- 微信、支付宝、百度等小程序平台的渲染层不支持
sticky,连基础属性识别都没有 - H5 端需同时满足:父容器有明确高度、无
overflow: hidden、无transform/filter/will-change,且子元素不能是flex且align-self: stretch - App 端(尤其是 iOS)依赖 Webview 内核,老版本 UIWebView 已弃用,WKWebView 对
sticky支持也不稳定 - 即使满足所有条件,
top值设为auto或漏写,也会直接失效
scroll-view + bindscroll 手动控制 fixed 是最稳方案
这是目前全平台(小程序/H5/App)兼容性最高、可控性最强的做法,核心是监听滚动位置,动态切换 class 控制定位状态。
- 必须给
scroll-view设置固定高度(如height: calc(100vh - var(--status-bar-height))),否则bindscroll不触发 -
offsetTop要在onReady或nextTick后获取,Vue 3 的onMounted中 DOM 可能还没渲染完,直接取会是0 - 吸顶后内容会上跳,必须加占位节点(比如一个空
view高度等于吸顶元素 height)或用padding-top补高 - 避免在
bindscroll回调里调用uni.createSelectorQuery()或getComputedStyle()——它们是同步阻塞操作,一帧内多次执行会卡顿甚至丢帧 - 用
requestAnimationFrame节流,防止高频滚动反复触发重排
使用 u-sticky 或 uview 的吸顶组件要注意什么
u-sticky 封装了 scroll 监听和 class 切换逻辑,但参数配置稍有不慎就失效,尤其在自定义导航栏或嵌套滚动场景下。
-
offsetTop单位是 rpx,若传0且页面有状态栏,吸顶会遮挡内容;建议根据uni.getSystemInfoSync().statusBarHeight动态计算 -
customNavHeight必须显式传入,否则在自定义导航栏下吸顶位置偏移 - 在
scroll-view内部使用时,u-sticky依赖父容器可滚动,若父容器没设scroll-y或高度不足,它会静默失效 -
disabled默认为false,但某些旧版 uView 未做响应式监听,改值后不会重新计算位置,需手动this.$forceUpdate()
list-view 场景下必须用 sticky-header 组件
如果你用的是 list-view(尤其在 App 端),别试图用 scroll-view 套一层来模拟——list-view 底层是原生 RecyclerView,CSS 定位不生效,只有它的专用吸顶组件才可靠。
-
sticky-header必须是list-view的**直接子节点**,嵌套在其他容器里会失效 - 多个吸顶区块要用
sticky-section配合,每个 section 对应一个吸顶标题,不能靠 class 切换模拟 -
sticky-header滚动出视口后会自动解除吸顶,但不会触发任何事件,如需联动高亮,得额外监听list-view的scroll事件并手动比对 item 位置 - 含
input或picker的吸顶区域,在 iOS 微信小程序中会被键盘顶起,此时要监听keyboardheight动态调整top值,不能只靠 CSS
真正难的不是写几行代码让导航“看起来吸顶”,而是确保它在 iOS 微信、安卓支付宝、H5 Chrome、App WKWebView 上行为一致——每个平台的渲染机制、滚动事件粒度、fixed 定位表现都不同,漏掉任意一个边界条件,上线后就会在某个用户手机上突然失效。











