position: sticky 在小程序全平台基本不可用,因底层未实现;H5 需满足父容器有高度、无 overflow: hidden、显式设 top 才生效;全端稳定方案是 scroll-view + bindscroll 手动控制 fixed 状态。

position: sticky 在 uni-app 中基本不可靠,不是你写错了,是微信、支付宝、百度、App 等多数平台压根没实现该 CSS 属性;H5 端虽支持,但必须同时满足三个硬性条件——父容器有明确高度、不能设 overflow: hidden、且必须显式声明 top 值(如 top: 0),缺一即失效。
为什么 position: sticky 在小程序里完全不生效
这不是兼容性“不好”,而是底层 WebView 或小程序运行时根本没解析这个声明。微信基础库、支付宝小程序 SDK、uni-app 编译后的 App 原生层均未注入 sticky 的滚动监听逻辑。你写的 .sticky-header { position: sticky; top: 0; } 在开发者工具里可能“看起来动了”,但真机一跑就回归文档流——因为样式被直接忽略。
常见错误现象:
- 元素在滚动中突然“跳回”顶部或消失
- H5 预览正常,但微信小程序里吸顶区域随页面一起滚动
- 设置了
top: 0仍无效,检查发现父级view没设height,或外层套了scroll-view但没限制高度
用 scroll-view + bindscroll 手动控制 fixed 状态
这是目前唯一全端稳定方案:监听滚动距离,动态切换 class 控制定位方式。关键不在“怎么写 CSS”,而在“什么时候切”和“切得准不准”。
实操要点:
- 给
scroll-view显式设置height(如height: calc(100vh - 100rpx)),禁用页面级滚动("pageStyle": "overflow: hidden") - 在
onReady或nextTick后读取吸顶元素的offsetTop,不要在onLoad里取,否则返回0 - 在
bindscroll回调中比较detail.scrollTop和缓存的headerTop,用data控制is-sticky状态 - CSS 中定义
.is-sticky { position: fixed; top: 0; left: 0; right: 0; z-index: 999; },并确保吸顶元素有占位节点(同高度的空view)防内容上移错位 - 加
requestAnimationFrame节流,避免高频触发重绘导致卡顿
sticky-header 组件仅适用于 list-view 场景
如果你用的是 list-view(非 scroll-view),那不能靠监听滚动手动切 fixed——list-view 底层基于 Android RecyclerView / iOS UITableView,DOM 不完整,offsetTop 取不到,bindscroll 也不触发。
此时必须用官方提供的 sticky-header 组件,它是 list-view 的一级子节点,不是普通 class:
- 它必须直接写在
list-view内部,不能嵌套在其他view里 - 一个
list-view只能有一个sticky-header,如需分段吸顶(如通讯录按字母),要配合sticky-section - 注意:该组件在
scroll-view中无效,强行使用会无响应
容易被忽略的细节:dpr 和字体缩放导致阈值漂移
别直接用固定像素值(如 scrollTop > 80)做判断。不同设备 dpr、系统字体缩放、甚至微信内置浏览器的渲染差异,会让实际吸顶位置偏移 2–10px,用户会明显感觉“卡一下”或“晚一帧才吸”。
正确做法是始终以元素真实 offsetTop 为准,并在 onResize 或窗口大小变化时重新获取——尤其当页面支持横竖屏切换或动态修改字体大小时。


















