前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库CSS animationstart animationend animationiteration 触发时机
CSS动画与视觉

animationstart、animationend、animationiteration 这三个事件分别在什么时候触发?

animationstart 在 animation-delay 结束、动画真正开始播放时触发。animationend 在全部循环播完后触发。animationiteration 在每一轮结束并进入下一轮时触发,第一轮开始时不触发,最后一轮结束时也不触发。

前端进阶之旅 · 一题精讲更新于 2026.09.29
CSS#动画与视觉#动画
先看核心答案读代码示例
理解线索

动画生命周期的三个时刻

  1. animationstart延迟结束、动画开始播放时触发,每个动画只触发一次
  2. animationiteration一轮结束并开始下一轮时触发,第一轮开始和最后一轮结束都不算
  3. animationend全部循环播完时触发,设了 infinite 就永远不会触发

如果 animation-delay 是负值,animationstart 仍然会触发,但事件对象的 elapsedTime 不是 0,而是跳过的那段时间。

核心回答

先记住这个答案

CSS 动画的生命周期有三个事件可以监听。animationstart 在 animation-delay 倒计时结束、动画真正开始播放那一刻触发,不管循环几次只触发一次。animationend 在所有循环全部播完之后触发。animationiteration 在前一轮结束并开始下一轮的瞬间触发,它只在两轮之间出现,第一轮开始时不算,最后一轮结束时也不算。

  • animationstart 等延迟结束才触发
  • animationend 在全部循环播完后触发
  • animationiteration 只在两轮之间触发
  • 无限循环动画不会触发 animationend

触发时序和延迟的关系

假设一个动画设了 animation-delay: 1s 和 animation-iteration-count: 3,每轮时长 2 秒。浏览器的执行时间线是这样的:0 到 1 秒什么事件都没有;1 秒时触发 animationstart;3 秒时第一轮结束进入第二轮,触发 animationiteration;5 秒时第二轮结束进入第三轮,再触发一次 animationiteration;7 秒时第三轮播完,触发 animationend。

用 JavaScript 监听这三个事件HTML
<div class="box">动画元素</div>
<style>
  .box {
    animation: slide 2s ease 1s 3; /* 延迟1秒, 每轮2秒, 共3轮 */
  }
  @keyframes slide {
    from { transform: translateX(0); }
    to   { transform: translateX(200px); }
  }
</style>
<script>
  const box = document.querySelector('.box');
  box.addEventListener('animationstart', e => {
    console.log('start', e.elapsedTime); // 0
  });
  box.addEventListener('animationiteration', e => {
    console.log('iter', e.elapsedTime); // 2, 4
  });
  box.addEventListener('animationend', e => {
    console.log('end', e.elapsedTime); // 6
  });
</script>

注意 elapsedTime 不包含 animation-delay 那段等待时间,它只计动画真正播放了多久。

负延迟和无限循环的特殊情况

如果 animation-delay 设成负值,比如 -1s,动画会跳过开头的 1 秒立刻开始播放。这时 animationstart 仍然会触发,但 elapsedTime 是 1 而不是 0,表示已经跳过了 1 秒的进度。

设了 animation-iteration-count: infinite 的动画永远不会触发 animationend。如果你的逻辑依赖 animationend 来做清理,遇到无限循环动画就会出问题。这时候应该用 animationiteration 来代替,在需要的那一轮结束时手动停止动画。

只播放一轮的动画,也就是 animation-iteration-count: 1,不会触发 animationiteration。因为它只在两轮之间出现,一轮的动画只有开始和结束,中间没有「两轮之间」的时刻。

实际场景:动画结束后移除元素

最常见的用法是在 animationend 里移除 DOM 元素或移除动画类名。比如一个 toast 提示做了淡出动画,淡出播完后从 DOM 里删掉。

监听 animationend 清理元素JavaScript
toast.addEventListener('animationend', () => {
  toast.remove();
}, { once: true });
toast.classList.add('fade-out');

这里用了 { once: true } 让监听器只执行一次,避免元素上有多个动画时多次触发。如果元素同时有好几个动画,animationend 会为每个动画各触发一次,需要通过事件对象的 animationName 属性判断是哪个动画结束了。

回答前,多想一步

容易答错的地方

以为 animationstart 在样式生效那一刻就触发
设了 animation-delay 的动画,animationstart 要等延迟结束才触发,不是样式一应用就触发。延迟期间元素处于等待状态,想在延迟期间就应用关键帧第一帧的样式,需要配合 animation-fill-mode: backwards。
把 animationiteration 和 animationend 搞混
animationiteration 在两轮之间触发,animationend 在全部循环播完后触发。最后一轮结束时只有 animationend,没有 animationiteration。同样,第一轮开始时只有 animationstart,没有 animationiteration。
试着用自己的话回答

面试官还会怎么问?

如果一个元素上同时有两个动画,事件触发几次?

每个动画独立触发。两个动画各自有自己的 animationstart 和 animationend,通过事件对象的 animationName 属性可以区分是哪个动画触发的。

transition 有没有类似的事件?

有。transition 有 transitionstart、transitionend、transitionrun 和 transitioncancel。区别在于 transition 没有循环的概念,所以没有对应 animationiteration 的事件。

动画被中途移除了,还会触发 animationend 吗?

不会。如果在动画播放过程中把 animation 属性去掉或者元素从 DOM 删除,animationend 不会触发。需要做清理的话,要在移除动画的代码里手动处理,不能依赖事件回调。

怎么只监听动画最后一轮结束?

直接用 animationend 就行,它只在全部循环播完后触发一次。如果需要在每一轮结束时做点事但只在最后一轮做不同的事,可以在 animationiteration 里计数,或者监听 animationend 做最后的逻辑。

从一道题,走向一组知识

把知识连起来

动画与视觉

@keyframes 里 from 和 to 跟百分比选择器是什么关系?

理解了事件的触发时机后,接着看 @keyframes 里百分比选择器和 from 以及 to 的对应关系,能更好地控制每一帧的样式。

动画与视觉

animation-play-state 暂停和负 animation-delay 跳过有什么区别?

animation-play-state: paused 暂停动画时不触发任何事件,和负 animation-delay 的快进效果对事件时序的影响值得对比。

参考资料

  • CSS:动画与视觉参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 触发时序和延迟的关系
  3. 负延迟和无限循环的特殊情况
  4. 实际场景:动画结束后移除元素
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑