animationend不触发的根本原因是CSS动画未真正执行,常见于初始与终态相同、动画时长为0、元素未挂载或display:none、animation-fill-mode误用等;需用getComputedStyle验证真实状态,避免依赖event.animationName,兼容性差时应加setTimeout回退。

animationend是最直接可用的事件,但实际用起来得绕几个坑才能稳。
为什么 animationend 有时不触发?
常见原因不是代码写错,而是动画根本没“播放”——比如元素初始状态就满足动画终点、animation-duration 为 0s、或者动画被 display: none 或 visibility: hidden 中断。
尤其注意:display: none 会彻底终止 CSS 动画,animationend 永远不会触发;改用 opacity: 0 + pointer-events: none 更安全。
- 检查浏览器开发者工具的 Animations 面板,确认动画是否真实运行
- 确保元素已挂载到 DOM 且可见(
offsetParent !== null) - 避免在添加动画 class 的同一帧立即移除 class 或隐藏元素
如何兼容老版本 Chrome / Safari / IE?
WebKit 内核早期必须用 webkitAnimationEnd,IE10 用 MSAnimationEnd。不能只监听一个。
推荐用前缀探测方式,而不是硬写多个 addEventListener:
function getAnimationEndEvent() {
const el = document.createElement('div');
const events = {
'animation': 'animationend',
'WebkitAnimation': 'webkitAnimationEnd',
'MSAnimation': 'MSAnimationEnd'
};
for (const prefix in events) {
if (el.style[prefix + 'Animation'] !== undefined) {
return events[prefix];
}
}
return 'animationend';
}
const animEl = document.getElementById('myAnim');
animEl.addEventListener(getAnimationEndEvent(), () => {
console.log('动画真结束了');
});
animationend 触发时能拿到哪些有用信息?
回调函数的事件对象 e 里有三个关键属性:
-
e.animationName:匹配触发该事件的具体@keyframes名,适合一个元素绑了多个动画时做分流 -
e.elapsedTime:动画实际运行秒数(不含 delay),可用于校验是否跳过 delay 或被强制中断 -
e.target:始终是触发动画的原始元素,不是伪元素或子元素
注意:e.pseudoElement 在 CSS 动画作用于 ::before 时为 '',无法监听伪元素动画结束。
和 transitionend 混用时要注意什么?
两者事件名不同、触发条件不同,但容易误判:
-
transitionend对每个过渡属性(如width、opacity)各触发一次;animationend整个@keyframes只触发一次 - 如果同时设置了
transition和animation,且它们时间重叠,两个事件可能先后触发,顺序不可靠 - 不要用
transitionend去监听@keyframes动画,它完全不响应
最稳妥的做法:动画用 animation + animationend,简单状态切换用 transition + transitionend,别混。
真正容易被忽略的是:动画中途被 JS 强制重置(比如修改 animation 属性值、或替换 class)会导致 animationend 永久失效——它不会补发,也不会触发 animationcancel(该事件尚未被主流浏览器支持)。所以关键逻辑别依赖“一定收到结束事件”,加超时兜底更实际。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











