应删除-webkit-overflow-scrolling: touch,因其在chrome 63+/safari 15.4+已废弃,残留使用会触发旧版滚动引擎降级;改用overscroll-behavior与will-change: scroll-position替代,并确保父容器有height/max-height。

DOM嵌套深度超6层直接拖慢touchstart响应
低端安卓机上,body > div > div > div > div > div > button这种结构会让 touchstart 到 handler 执行延迟达 42ms;而三层语义化结构(如 <main><nav><button></button></nav></main>)稳定在 8–12ms。这不是 JS 执行慢,是事件冒泡路径太长,中间任意一层设了 pointer-events: none 或 touch-action: none 就可能中断。
- 用 Chrome DevTools → Elements 面板右键元素 →
Show DOM properties查看depth值,超过 6 必须重构 - 别为加 class 套
<div>:改用 <code>display: contents(Safari 15.4+ 支持)抹除无意义包裹层 <td> 里禁止嵌套 <code><div>:表格单元格内样式匹配成本高,混用 flex 容器极易触发重排 <h3>scroll事件监听未设passive: true导致主线程阻塞</h3> <p>移动端浏览器默认把 <code>scroll当作“可能调用preventDefault()”的事件,会等 JS 执行完才滚动——哪怕你根本没写preventDefault()。不加{ passive: true },Chrome 控制台会报Unable to preventDefault inside passive event listener,真机上就是肉眼可见的延迟。- 必须写成:
window.addEventListener('scroll', handleScroll, { passive: true }) - 若真要阻止滚动(如下拉刷新),改用
touchstart+touchmove,并在必要时显式设passive: false - 兼容性没问题:Chrome 51+、Firefox 53+、Safari 11.1+、Edge 79+ 全支持
图片未设fetchpriority="high"和decoding="async"卡住主线程
首屏关键图默认被标记为
low优先级,哪怕它是 LCP 候选元素;解码也默认同步执行。一张 200KB 的图就能让主线程停顿,滚动瞬间掉帧。- 首屏图必须加:
<img fetchpriority="high" loading="eager" ...> - 大于 100KB 的图建议加:
decoding="async" - SVG 或小图标不用加
decoding,它只对位图生效 - 别依赖
loading="lazy":它会推迟首屏图加载,和滚动流畅度冲突
overflow-y: scroll + -webkit-overflow-scrolling: touch 在 Safari 中不稳定
这个组合在 iOS Safari 和微信 WebView 里常出现“点一下能滑、再点就卡住”或“滑动一段后突然失灵”的现象。它会创建新堆栈上下文,还容易和 fixed 定位、transform 元素冲突。
- 优先用自然流式布局:给
main设padding-top/bottom,靠body自带滚动,避免手动干预 - 若必须局部滚动,用
position: absolute替代fixed,并确保父容器有明确高度 - 禁用
-webkit-overflow-scrolling: touch后,滚动虽无回弹,但稳定性显著提升 - 真需要回弹效果,用
transform: translateY()+will-change: transform自建,比原生属性更可控
passive: true这两项——它们不报错、不抛异常,但一到低端机就暴露得特别彻底。- 必须写成:











