最推荐方案是给 body 设置 overscroll-behavior: none,需配合 height: 100% 和 overflow: hidden 才生效;scroll-view 要设 scroll-y 和固定高度,避免 -webkit-overflow-scrolling: touch;inobounce 仅适用于根滚动禁用场景。

直接禁用 body 的 overscroll 行为
iOS Safari 的回弹本质是 overscroll(溢出滚动)触发的系统级动画,不是 CSS 滚动本身的问题。最轻量、最推荐的第一步是给 body 设置 overscroll-behavior: none —— 它能直接切断顶部/底部拉伸的源头,且不影响内部滚动容器的正常使用。
-
overscroll-behavior: none必须作用于body或html,仅设在子容器上无效 - 需搭配
height: 100%和overflow: hidden才能确保生效(否则部分 iOS 版本会忽略) - 该属性在 iOS 13+ 全面支持,低于此版本会降级为无效果,需 fallback 方案
scroll-view 组件内滚动失效或冲突
uni-app 的 <scroll-view> 在 iOS H5 下常因父级 body 溢出而被“劫持”滚动权,导致内部列表卡顿、无法滑到底部、或触发行间回弹。这不是组件 bug,而是滚动事件冒泡与系统行为叠加的结果。
- 必须给
<scroll-view>显式设置scroll-y和固定高度(如height: 600rpx),不能依赖flex: 1或100vh(后者在 Safari 中计算不准) - 避免同时设置
-webkit-overflow-scrolling: touch—— uni-app 内部已封装该行为,手动加反而引发双滚动层冲突 - 若仍回弹,检查是否在
<scroll-view>外层包裹了position: fixed或absolute的容器,这类定位会干扰滚动上下文
touchmove preventDefault 的坑与写法
用 event.preventDefault() 确实能压住回弹,但极易误伤正常滚动——比如你阻止了整个页面的 touchmove,结果 <scroll-view> 也动不了了。
- 不要全局监听
document的touchmove并无条件preventDefault(),这等于废掉所有滚动 - 正确做法是:只在需要锁定的场景(如弹窗打开时)对特定区域监听,并判断
event.target是否属于非滚动元素(例如遮罩层、按钮) -
{ passive: false }必须显式传入,否则 iOS 会忽略preventDefault();但频繁调用会影响性能,慎用
inobounce 插件的适用边界
inobounce 是专治 iOS overscroll 的小工具,但它只解决“根滚动”的回弹,对嵌套的 <scroll-view> 或自定义滚动容器无效。
- 适合场景:全屏弹窗、loading 层、遮罩态下禁止背景滚动 —— 此时调用
inobounce.enable()即可 - 不适合场景:日常页面主内容区、带复杂嵌套滚动的仪表盘 —— 它不控制子容器,反而可能掩盖真实问题
- 注意它会修改
document.body的样式,若页面有多个滚动入口(如 tab 切换),需在关闭时调用inobounce.disable()清理
真正稳定的方案永远是分层处理:根节点用 overscroll-behavior 截断,滚动容器用明确尺寸 + 正确属性隔离,交互态再用脚本精细干预。iOS 回弹不是“开关问题”,而是滚动上下文归属问题 —— 谁该滚动、谁不该滚动,得在 DOM 结构和 CSS 规则里就定清楚。


















