滚动文字应优先用 transform: translatey() 而非 top/margin-top,因其属合成层操作,可避免布局重排;需配合 translatez(0)、整数对齐、固定行高、字体预加载及合理分层等优化策略。

滚动文字用 transform: translateY() 而不是 top 或 margin-top
直接改 top 或 margin-top 会触发 Layout(布局重排),浏览器必须重新计算整个文档流,尤其在文字容器嵌套深、字体多、有阴影或边框时,帧率明显掉。而 transform: translateY() 属于合成层操作,只要该元素已提升为独立图层(通常靠 will-change: transform 或 transform: translateZ(0)),GPU 就能直接位移像素块,不碰主线程布局逻辑。
实操建议:
- 给滚动容器加
transform: translateZ(0)强制创建合成层(注意:别滥用,每个合成层占显存) - 动画用
requestAnimationFrame驱动transform,避免setTimeout+ 样式写入 - 禁用
transition做滚动——它不可控、易卡顿,且无法暂停/跳转 - 若用 CSS
@keyframes,确保只 animatingtransform和opacity,其他属性一加就退化到软件渲染
避免滚动容器内文字频繁重排(reflow)
哪怕用了 transform,如果文字内容动态插入、字体加载中、或行高/字宽因字号/语言切换变化,仍会触发 Layout,拖慢首帧和持续滚动。
常见错误现象:
立即学习“前端免费学习笔记(深入)”;
- 中英文混排后突然卡顿 → 字体未加载完,浏览器等 fallback 字体回填导致重排
- 滚动中文字“跳动”或错位 → 行高随内容长度变化(如
line-height: normal或em单位未固化) - 文字模糊 → 缩放或 subpixel 渲染未对齐,常因
transform值含小数且未math.round()对齐
实操建议:
- 预设固定
line-height(推荐px或无单位数值,如line-height: 1.4),禁用normal - 用
@font-face的font-display: swap,并提前加载关键字体;或用document.fonts.load()等待就绪再启动滚动 - 滚动位移值做整数对齐:
element.style.transform = `translateY(${Math.round(y)}px)`
滚动区域层级别乱堆 z-index 和透明遮罩
多个重叠的 z-index 层、半透明背景、backdrop-Filter、甚至带 box-shadow 的父容器,都会让浏览器放弃图层合并,强制为每个元素单独绘制+合成,GPU 负担陡增。
使用场景里最典型的是“滚动文字+渐变遮罩+标题浮层”,三者若没合理分层,chrome DevTools 的 Layers 面板里能看到十几个碎片图层。
实操建议:
- 把滚动文字容器设为
isolation: isolate,明确其为独立合成上下文,避免被外层样式污染 - 遮罩用
linear-gradient写在background里,别用额外 dom 元素盖一层半透明div - 禁用
backdrop-filter在滚动区域上(ios safari 尤其吃资源);如需毛玻璃效果,用静态截图+伪元素替代 - 检查
box-shadow是否真必要——滚动中阴影每帧重绘开销大,可考虑用filter: drop-shadow()(同属合成友好属性)
移动端 iOS Safari 的 overflow: scroll 滚动文字慎用
iOS Safari 对 overflow: scroll 容器内的子元素动画极其敏感,哪怕只动 transform,一旦容器高度不固定、或内部有 flex / grid 布局,就容易掉帧甚至卡死。这不是 bug,是 webkit 的滚动优化策略决定的:它会把整个 overflow 区域当做一个“滚动视口”,禁止对其子节点做独立合成。
实操建议:
- 优先用
position: absolute+transform滚动,而非依赖overflow: scroll - 若必须用
overflow,确保容器height固定、will-change: scroll-position(仅限 Safari 15.4+)、且内部无弹性布局 - 测试务必真机跑——模拟器无法复现 WebKit 的图层调度行为
滚动文字性能问题,核心不在“怎么动”,而在“动的时候别让浏览器干别的事”。合成层是否干净、文字度量是否稳定、移动端是否绕开了 WebKit 的滚动陷阱——这三点漏掉任一个,优化都白搭。