监听CSS动画或过渡结束需用transitionend/animationend事件,注意多次触发、冒泡、中断不触发等问题,并用兼容性检测和once:true确保健壮性。

监听 CSS 动画或过渡结束,核心是用 addEventListener 绑定 transitionend 或 animationend 事件。但直接写容易踩坑——比如多次触发、子元素干扰、兼容性缺失、或动画被提前中断导致事件不触发。
transitionend 事件监听要点
当元素的 CSS transition 完成时触发。注意以下关键细节:
- 多个属性同时过渡(如
width、opacity、transform)会触发多次transitionend,每次对应一个完成的属性;可用e.propertyName判断具体哪个属性结束 - 事件会冒泡到父级,若子元素也有过渡,也会触发该监听器;建议加守卫:
if (e.target !== element) return - 若在动画中途设置
display: none或移除元素,事件将**永不触发**;应改用visibility: hidden或延后移除 - 过渡必须“真正发生”才触发:从
display: none→block不算过渡;需先设为可见,再触发动画(例如先设opacity: 0+visibility: visible,再过渡opacity: 1)
animationend 事件监听要点
对应 @keyframes 定义的 CSS 动画播放完毕时触发:
使用约定式提交(Conventional Commits)生成标准化的 Git 提交信息。适用于以下场景: (1) 暂存更改时需要提交信息; (2) 审查 diff 时希望获得结构化摘要; (3) 编写 PR 描述或变更日志(changelog)条目; (4) 用户明确要求“为本次更改编写提交信息”。 该功能会分析已暂存/未暂存的 diff,并生成按类型(type)划分范围的提交信息。
- 同样存在冒泡问题,子元素动画结束也会触发父级监听器,务必校验
e.target === element - 动画若被
animation-play-state: paused暂停,再恢复不会重新触发animationend;只有完整播放一次才会触发 - 使用
animation-iteration-count: infinite时,animationend**永远不会触发**;如需循环回调,应监听animationiteration - 动画名可通过
e.animationName获取,适合同一元素绑定多个 keyframes 场景
兼容性与健壮写法
旧版 WebKit(Safari ≤ 6、Android ≤ 4.3)需要前缀。推荐封装一个通用检测函数:
const getTransitionEndEvent = () => {
const el = document.createElement('div');
const transitions = {
'transition': 'transitionend',
'OTransition': 'oTransitionEnd',
'MozTransition': 'transitionend',
'WebkitTransition': 'webkitTransitionEnd'
};
for (const t in transitions) {
if (el.style[t] !== undefined) return transitions[t];
}
return 'transitionend';
};
const getAnimationEndEvent = () => {
const el = document.createElement('div');
const animations = {
'animation': 'animationend',
'OAnimation': 'oAnimationEnd',
'MozAnimation': 'animationend',
'WebkitAnimation': 'webkitAnimationEnd'
};
for (const a in animations) {
if (el.style[a] !== undefined) return animations[a];
}
return 'animationend';
};
// 使用示例
element.addEventListener(getTransitionEndEvent(), e => {
if (e.target !== element) return;
console.log('过渡完成:', e.propertyName);
});
避免重复执行的简单控制
过渡/动画只需执行一次回调(比如切换 class、释放锁、清理定时器),可用布尔标记或 { once: true } 选项:
- 推荐用
once: true:简洁安全,自动解绑,无需手动管理 - 若需复用监听器(如轮播图每张图都监听),可用闭包变量或
data-属性标记状态 - 慎用全局 flag,多实例场景易冲突

















