position: sticky 在 uni-app 多端下基本无效,因小程序平台未实现该属性,h5 端需满足父容器有高度、无 overflow: hidden、显式设 top 才生效;推荐 scroll-view + bindscroll 手动控制 fixed 或 list-view 的 sticky-header 组件。

uni-app 里直接写 position: sticky 基本无效——不是你 CSS 写错了,是微信、支付宝、百度等小程序平台压根没实现这个属性;H5 端虽支持,但必须同时满足父容器有高度、无 overflow: hidden、显式设 top 三个条件,缺一即失效。
为什么 position: sticky 在 uni-app 多端下大概率不工作
常见错误现象包括:H5 预览看着正常,真机调试时“掉下来”;iOS 微信小程序里完全没反应;安卓低端机滚动卡顿甚至错位。根本原因在于:
- 微信/支付宝/百度等小程序的渲染层不解析
sticky声明,样式被直接忽略 - H5 端受浏览器内核限制:父容器若带
transform、filter或是flex且子项align-self: stretch,sticky会静默失效 - App 端依赖 Webview,老版本 UIWebView 已弃用,WKWebView 对
sticky支持也不稳定 -
top值设为auto或漏写,等于放弃吸顶
scroll-view + bindscroll 手动控制 fixed 是最稳方案
这是目前全平台(小程序/H5/App)兼容性最高、可控性最强的做法,核心是监听滚动距离,动态切换 class 控制定位状态:
-
scroll-view必须显式设置height(如height: calc(100vh - var(--status-bar-height))),否则bindscroll不触发 -
offsetTop要在onReady或$nextTick后读取,onLoad或onMounted中 DOM 可能未渲染完,取值为 0 - 在
bindscroll回调中比较detail.scrollTop和缓存的headerTop,用data控制is-sticky状态 - CSS 中定义
.is-sticky { position: fixed; top: 0; left: 0; right: 0; z-index: 999; },并确保吸顶元素下方有同高度占位节点(空view),防内容上移错位 - 用
requestAnimationFrame节流,避免高频触发重绘导致卡顿
用 list-view 时必须走 sticky-header 组件
如果你用的是 list-view(非 scroll-view),不能靠监听滚动手动切 fixed——因为 list-view 底层基于原生控件(Android RecyclerView / iOS UITableView),DOM 不完整,offsetTop 取不到,bindscroll 也不触发:
-
sticky-header必须是list-view的一级子节点,不能嵌套在其他view里 - 它和配套的
sticky-section可组合实现分段吸顶(如通讯录字母索引) - 整个页面结构需以
list-view为根,顶部 banner、中间表头、底部 item 全部作为其子节点 - 不要给
sticky-header自行加position: sticky,它内部已封装滚动锚定逻辑
真正难的不是“怎么写”,而是判断当前场景该用哪条路径:页面级滚动?用 scroll-view + bindscroll;长列表复用需求强?必须切 list-view + sticky-header;而所有想靠纯 CSS sticky 一劳永逸的尝试,在真机上基本都会撞墙。











