苹果手机局部滚动卡顿的核心原因是误用已废弃的 -webkit-overflow-scrolling: touch,该属性在 safari 15.4+/ios 15.4+ 中会破坏原生滚动管线、引发惯性消失和主线程阻塞;应彻底删除,并确保容器有明确高度(如 height 或 max-height)、避免合成层干扰(禁用 filter/transform 等)、所有 touchmove/scroll 事件监听必须设 { passive: true }。

苹果手机上局部滚动卡顿,核心问题不在“没加硬件加速”,而在于现代 iOS 已废弃旧机制却仍被误用——-webkit-overflow-scrolling: touch 在 Safari 15.4+ 和 Chrome 63+ 中已成反模式,加了反而破坏原生滚动管线。
删掉 -webkit-overflow-scrolling: touch
这行 CSS 不是“没加才卡”,而是“加了才卡”。它会强制降级到旧滚动线程,导致惯性消失、touchmove 同步阻塞主线程。DevTools Elements 面板全局搜索,只要存在就删除;还要检查 JS 是否动态注入(比如某些 UI 库初始化时偷偷加上)。
确保滚动容器高度明确且可截断
局部滚动失效的常见原因是父容器没设 height 或 max-height,子元素 overflow-y: scroll 就不生效——滚动区域根本没被截断。
- 用固定值(如 height: 400px)或视口单位(如 max-height: 70vh)显式声明高度
- 避免用 height: auto、min-height: 100% 或 flex: 1(未配 min-height: 0)这类弹性值
- 在 iOS 中慎用 100vh,地址栏收起会导致视口变化、容器塌缩;改用 100dvh(iOS 16.4+ 支持)或 JS 动态 fallback
避免合成层干扰与错误加速
滚动容器内若含 transform、opacity、filter 的子元素,WebKit 会无序升层,打断滚动线程;will-change: transform 更不能乱加。
- 禁止给列表项(如 .item)写 will-change: transform —— 一屏 10 个,滚动中常驻 20+ 图层,中低端机 GPU 显存吃紧,帧率跌破 20fps
- 需要触发合成层时,只对滚动容器本身加 transform: translateZ(0) 或 translateY(0),且必须配合真实位移(不能只写空 transform)
- 用 Chrome DevTools → Layers 面板确认图层数:稳定在 3~5 层为佳,超过 8 层立刻排查
滚动监听必须带 passive: true
哪怕只写了一行 window.addEventListener('scroll', handler),iOS 上滚动帧率也可能从 60fps 掉到 20fps——因为默认 passive 是 false,浏览器必须等 JS 执行完才能继续滚动。
- 所有滚动监听必须显式传 { passive: true }
- 需阻止默认行为(如下拉刷新),改用 touchstart + preventDefault(),别在 scroll 回调里调
- 避免在 scroll 里读取 scrollTop、getBoundingClientRect() 或写 style —— 这会强制同步回流(layout thrashing)
- 用 IntersectionObserver 替代实时滚动计算,比如“滚动到某位置显示按钮”











