用 translatex 做无限滚动公告卡顿,主因是未触发硬件加速,需加 will-change: transform 或 translatez(0);同时注意容器上下文、动画时长、动态宽度计算、无缝衔接、touch 暂停恢复及旧浏览器兼容。

translateX动画卡顿或跳帧
用 translateX 做无限滚动公告,最常遇到的不是停不下来,而是视觉上“一顿一顿”。这不是代码写错了,而是浏览器没把它当“可硬件加速”的任务来处理。
关键点就一个:必须给动画元素加上 will-change: transform,或者更稳妥地加 transform: translateZ(0)。否则 Chrome/Firefox 可能复用普通重绘流程,尤其在低端设备或页面已有大量 DOM 时,帧率直接掉到 30fps 以下。
- 别只在
@keyframes里写translateX,父容器也要有触发层叠上下文的属性(比如overflow: hidden) - 动画时长别设太短,
15s比3s更稳——不是越快越炫,是越慢越顺 - 文字内容动态插入时,避免直接操作
innerHTML,改用textContent+DocumentFragment防止重排
无缝循环断裂:首尾衔接对不齐
跑马灯滚动到头又从头开始,中间总有一小段空白或重叠,本质是位移距离和容器宽度没对齐。不是“多试几次数值”,而是得算清楚两个长度:可视区宽、文案总宽。
假设容器 .marquee 宽 600px,里面文字撑开后总宽 1280px,那一次完整平移就得是 -1280px,但动画终点要回到 0 才能无缝。所以 @keyframes 得写成从 0 到 -1280px,再立刻跳回 0,不能靠“循环播放自动接上”。
立即学习“前端免费学习笔记(深入)”;
- 用
getBoundingClientRect().width动态读取文字宽度,别硬编码 - 动画延迟(
animation-delay)别设负值去“抢跑”,容易在 Safari 里失准 - 如果文字是中英文混排,注意
font-display: optional可能导致首次渲染宽度突变,先占位再替换
移动端 touch 操作打断动画
手指一划屏幕,跑马灯就卡住不动了,松手也不恢复。这是浏览器把 transform 动画判定为“非用户交互友好”,主动暂停了。不是 bug,是规范行为。
解决方式很直接:监听 touchstart,暂停动画;touchend 后用 setTimeout 延迟 16ms 再恢复。不能立刻恢复,否则 iOS WebKit 会忽略。
- 暂停用
element.style.animationPlayState = 'paused',别删 class - 恢复时别用
'running',而是先设成'paused'再设回'running',强制重触发 - 如果页面还用了
passive: true的 touch 事件监听,得显式改成false,不然拿不到preventDefault控制权
IE11 或旧版 Safari 不支持 animation-fill-mode: forwards
老系统下动画播完直接闪回起点,公告消失。问题不在 translateX,而在你依赖 forwards 保持最终位移状态——IE11 根本不认这个值,Safari 9.1 以前也只支持部分。
绕过办法只有一个:不用 forwards,改用 JS 监听 animationend,手动补上最终 transform 值。而且得兼容两种事件名:webkitAnimationEnd 和标准名。
- 监听前先检查
element.style.animationName是否为空,防重复绑定 - 补位移时用
element.style.transform = 'translateX(-1280px)',别用style.cssText全量覆盖 - 如果动画被 JS 中断过(比如上面 touch 暂停),
animationend可能不触发,得加兜底定时器










