删掉已废弃的 -webkit-overflow-scrolling: touch 是首要任务,因其在 ios 15.4+/safari 16+ 中失效并导致滚动降级;同时需确保容器高度确定以激活惯性滚动。

因为“CSS弹性滚动”本身不是标准概念,iOS 上所谓“弹性滚动”实际依赖原生滚动上下文,而大量非必要样式、错误监听和废弃属性会直接破坏该上下文,导致合成层无法建立或事件链被阻塞。
删掉 -webkit-overflow-scrolling: touch 是第一要务
这个属性在 iOS 15.4+ 和 Safari 16+ 中已被废弃,浏览器不再响应它,反而会降级到旧滚动引擎:iOS 上丢失惯性,Android 上 touchmove 同步阻塞主线程,帧率常跌破 20fps。Chrome DevTools → Elements 面板全局搜索就能定位,只要存在就删。
- 检查 JS 是否动态注入——某些 Bootstrap 封装组件在
init()时偷偷加上 - 别信“模拟器不生效所以真机要加”,真机上加了才真正出问题
- 它不会启用硬件加速,只干扰渲染管线
容器高度不确定 = 滚动上下文失效
iOS Safari 必须确认可滚动范围才能激活惯性,height: auto 或靠 flex 内容撑开的容器,scrollHeight 时根本不会启用滚动引擎。
- 父容器必须有确定高度:
html, body { height: 100% };Flex 容器中子项需加min-height: 0 - 滚动容器自身用
max-height或100dvh(避免100vh,地址栏展开会跳变) - 确保子内容略超容器高,可用
height: calc(100% + 1px)强制判定成立
touchmove 和 scroll 事件没设 { passive: true }
这是最常被跳过、效果却最立竿见影的一环。默认 passive: false 会让浏览器暂停滚动等待 JS 执行完,iOS 上手势延迟甚至冻结是常态。
- 错误写法:
el.addEventListener('touchmove', handler) - 正确写法:
el.addEventListener('touchmove', handler, { passive: true }) - 同理适用于
scroll事件;如需阻止默认行为(如下拉刷新),改用touchstart+e.preventDefault()
合成层被干扰或滥用
真正影响流畅度的是浏览器能否为滚动容器创建独立合成层,而 filter、opacity: 0.99、backdrop-filter、transform 等样式若出现在祖先链上,会强制重绘或打断图层提升。
- 禁用
.item { will-change: transform }这类全局规则——一屏 15 个列表项 = 15 个 GPU 图层,中低端安卓机显存吃紧 -
will-change: scroll-position只在 iOS 15+ 有效,旧版无效,别滥用 - 用 Chrome DevTools → Layers 面板看图层数:稳定在 3~5 层为佳,超过 8 层立刻排查
卡顿从来不是单一原因,而是高度、事件、合成层、废弃属性四者叠加失效的结果。最容易被忽略的是:你以为在“开启弹性”,其实只是在不断触发浏览器的兼容性降级逻辑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











