移动端滚动卡顿的根源是废弃的-webkit-overflow-scrolling: touch被残留使用,触发旧版滚动引擎降级;应删除该声明,确保父容器有height/max-height,并用overscroll-behavior与will-change: scroll-position替代。

移动端滚动卡顿的根源是-webkit-overflow-scrolling被移除
Chrome 63+ 和 Safari 15.4+ 已废弃 -webkit-overflow-scrolling: touch,但很多老项目仍保留该声明,反而触发浏览器降级处理——它会强制启用旧版滚动引擎,导致 iOS 上惯性滚动失效、Android 上 touchmove 阻塞主线程。这不是“没加”,而是“加了反而坏”。
- 检查 DevTools 的 Elements 面板,搜索
-webkit-overflow-scrolling;如果存在,直接删掉 - 确认没有通过 JavaScript 动态注入该样式(比如某些 UI 库的初始化逻辑)
- 若删除后滚动仍卡顿,大概率是父容器
overflow值不匹配:子元素设了overflow-y: scroll,但父容器没设height或max-height,导致滚动区域未被正确截断
替代方案:用 overscroll-behavior + will-change 激活原生滚动
现代浏览器靠 overscroll-behavior 控制滚动链路,配合 will-change: transform 提前提示渲染器启用合成层,比旧式 hack 更稳定。
-
overscroll-behavior-y: contain可阻止滚动穿透(比如弹窗内滚动到底部时,背景页跟着动) -
will-change: scroll-position在滚动容器上设置,比transform更语义化,且不会意外触发重排 - 注意:不要在所有滚动容器上滥用
will-change,仅对高频滚动区域(如列表、轮播)设置
iOS Safari 卡顿常因 transform 层叠上下文破坏滚动优化
当滚动容器内部有 transform、opacity 或 filter 的子元素时,WebKit 会将其提升为独立图层,但若该图层尺寸过大或频繁重绘,就会打断滚动线程。这不是性能差,是图层管理失控。
- 用 DevTools 的 Layers 面板(Rendering → Show layer borders)查看是否出现异常大图层
- 避免在滚动容器内使用
transform: scale(0.99)这类“伪 hack”来触发硬件加速——它制造了无意义图层 - 用
contain: layout paint显式声明子元素不影响外部布局,减少滚动时的重绘范围
滚动监听器本身就会导致卡顿
哪怕只写了一行 window.addEventListener('scroll', handler),在 iOS 上也可能让滚动帧率从 60fps 掉到 20fps——因为默认 passive 是 false,浏览器必须等 JS 执行完才能继续滚动。
- 所有滚动监听器必须显式传
{ passive: true },否则 Chrome 和 Safari 都会警告并降级 - 需要阻止默认行为(如下拉刷新)时,改用
touchstart+preventDefault(),而不是在scroll里调用 - 用
requestIdleCallback或IntersectionObserver替代实时滚动计算(比如“滚动到某位置显示按钮”)
真正卡顿的地方往往不在滚动本身,而在滚动触发的副作用:重排、重绘、JS 同步执行、图层合成失败。修复前先开 DevTools 的 Rendering 面板勾选 “FPS Meter” 和 “Layer Borders”,看帧率和图层是否异常——别猜,要看。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











