连续动画需用animation-duration、delay和fill-mode精确衔接,关键在forwards保持末帧状态,各段delay累加且keyframes首尾状态一致,避免transform覆盖导致闪回。

连续动画不是靠堆多个 animation 属性硬拼,而是用 animation-duration + animation-delay + animation-fill-mode 精确控制每段的起止状态,让后一段自然接上前一段的结束位置。
animation-fill-mode 是衔接成败的关键
默认情况下,动画结束后元素会“弹回”初始样式,导致下一段动画从头开始跳——这就是衔接断裂的根源。必须显式设置 animation-fill-mode:
-
forwards:动画停在最后一帧,保持该状态,为下一段提供起点 -
both:兼顾开始前(backwards)和结束后(forwards),适合首尾都需要预设状态的场景 - 千万别省略,也别只写
animation简写——它会把fill-mode重置为默认的none
多段动画如何用 CSS 串起来
核心是让第 n 段的 animation-delay 等于前 n−1 段总时长,并确保每段都带 forwards:
- 第一段:
animation: fade-in 0.3s ease forwards; - 第二段(淡入后缩放):
animation: scale-up 0.4s ease 0.3s forwards;(延迟 = 第一段时长) - 第三段(缩放后平移):
animation: slide-right 0.5s ease 0.7s forwards;(延迟 = 0.3 + 0.4)
注意:所有动画的 @keyframes 必须以 0% 状态兼容上一段的 100% 结束态。比如第二段的 0% 应该和第一段的 100% 完全一致(包括 transform、opacity、color 等)。
用 JavaScript 控制连续动画更可靠
CSS 串连在复杂交互中容易失控,尤其是需要暂停、跳转或响应数据变化时。推荐用 JS 显式管理状态:
- 给元素加一个
data-step="0",每完成一段就递增并切换 class - 监听
animationend事件,但只用于非infinite动画——无限循环下这个事件不触发 - 避免反复增删 class 触发重排;改用
element.style.animation动态赋值,并在赋值前后读一次offsetWidth强制重排生效 - 示例关键逻辑:
el.addEventListener('animationend', () => { const step = parseInt(el.dataset.step) + 1; el.dataset.step = step; el.className = `anim-step-${step}`; });
常见断裂点:transform 合成与重置冲突
如果某段动画用了 transform: translateX(100px),下一段又写了 transform: scale(1.2),浏览器会直接覆盖整个 transform 值,丢失之前的位移——结果就是“闪回原点”。
- 正确做法:所有 transform 操作合并到同一声明里,例如
transform: translateX(100px) scale(1.2) - 或者用 CSS 自定义属性动态注入,避免硬编码覆盖:
transform: translateX(var(--tx, 0)) scale(var(--scale, 1)); - 慎用
transform: none——它会清空全部 transform,不是“不执行”,而是“重置为初始矩阵”
真正难的不是写几段动画,而是让它们像齿轮一样咬合转动:前一段的终点,必须是下一段无可争议的起点。任何一处 fill-mode 遗漏、transform 覆盖或 delay 计算偏差,都会让连续性当场失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











