用CSS动画+animation-delay精确编排序列需为每个元素单独设置延迟,延迟值等于前序动画时长累加;复杂逻辑需监听animationend事件链式触发;transition因无完成信号且依赖属性变更时机,不适合多步序列。

动画序列如何用 CSS 动画 + animation-delay 精确编排
纯 HTML 无法直接控制动画序列,必须依赖 CSS 动画或 JavaScript 驱动。最轻量、最可控的方式是用 @keyframes 定义基础动画,再通过 animation-delay 逐个错开触发时机。
常见错误是把多个动画写在同一个 animation 声明里试图“串联”,结果所有元素同时开始——animation 不支持序列参数,只接受单个动画名 + 时长 + 延迟等独立值。
- 每个组件需单独设置
animation-delay,延迟值 = 前序动画总时长 × 序号(从 0 开始) - 若使用
animation-fill-mode: forwards,注意延迟期间元素仍保持初始状态,不会提前渲染终态 - 动画时长不一致时,不能简单按序号乘固定值,得累加前序
animation-duration - 用
data-index属性配合 CSS attribute selector 可批量控制,例如:[data-index="2"] { animation-delay: 1.2s; }
用 animationend 事件链式触发更灵活的序列
当动画逻辑复杂(比如某步需用户交互才继续,或要动态计算延迟),CSS 的静态延迟就不够用了。这时得监听 animationend 事件,在上一个动画结束时手动给下一个元素添加动画 class。
关键点在于:事件只在动画自然结束时触发,强制中断(如 class 移除)不会触发;且需用 event.animationName 判断是否是目标动画,避免伪元素或过渡动画干扰。
立即学习“前端免费学习笔记(深入)”;
- 给每个组件设唯一标识(如
id或data-step),方便事件回调中定位下一个 - 首次触发要用
setTimeout或requestAnimationFrame包一层,避开 DOM 渲染队列问题 - 移除动画 class 后再重新添加,可重置动画状态,否则重复添加无效
- 示例片段:
el.addEventListener('animationend', () => { document.getElementById('step-2').classList.add('animate-in'); });
为什么不用 transition 做序列?它和 animation 的根本区别在哪
transition 不适合做多步序列,因为它只响应属性变化(比如 opacity、transform),没有明确的“播放完成”信号,也无法定义中间关键帧。你只能靠 JS 手动改属性来推进,但无法精确知道上一步何时真正结束渲染。
典型踩坑:用 setTimeout 模拟延迟 transition,结果因浏览器渲染帧率波动或 JS 主线程阻塞导致卡顿、错序。
-
animation有确定的duration和delay,浏览器可调度合成层动画,性能更好 -
transition的持续时间受属性变化时机影响,比如连续 setStyle 会被合并,导致实际过渡被跳过 - 只有
animation能触发animationend,transition对应的是transitionend,但后者无法保证与视觉结束严格同步 - 需要逐帧控制或循环序列时,
@keyframes是唯一可靠选择
用 Web Animations API 替代 CSS 的真实收益和代价
如果项目已用现代浏览器为主,Element.animate() 提供了比 CSS 更细粒度的控制:能读取当前播放进度、暂停/反转/取消任意动画、组合多个动画效果。但它不是“更简单”的替代,而是“更重但更可控”的方案。
容易忽略的代价:每个 animate() 调用都会创建新动画实例,不手动 cancel() 就会内存泄漏;且无法复用 CSS 中预定义的 @keyframes,必须用 JS 对象重写关键帧。
- 适合场景:动态生成动画(如数据驱动的图表入场)、需要实时调整播放速率、或与滚动/拖拽深度耦合
- 避免滥用:静态页面上的固定序列,用 CSS 更轻量、更易维护
- 检查兼容性:
Element.animate在 Safari 16.4+ 才完全支持effect参数,旧版本需降级 fallback - 获取当前状态:
const anim = el.animate(...); console.log(anim.currentTime);
动画序列真正的复杂点不在“怎么动”,而在“什么时候动”和“动完之后怎么交棒”。延迟值算错、事件监听漏绑、CSS class 清理不干净,这三类问题占了调试时间的八成以上。



















