如何在CSS动画完成后实现反向播放?
解决CSS动画完成后反向播放的问题
我明白你遇到的困扰了——当初始动画结束后给元素添加带animation-direction: reverse的类,结果元素直接跳回初始状态,完全没有平滑的反向播放过程。这其实是因为浏览器没有重新触发动画,只是修改了动画属性但没执行它。
问题根源
如果你的初始动画用了animation-fill-mode: forwards让元素停在结束状态,直接添加反向类时,浏览器会认为动画属性的变化不需要重新执行动画——它只会直接应用反向动画的"最终状态"(对应原动画的初始状态),但不会播放中间的动画过程,所以看起来就像瞬间跳回去了。
解决方案:强制重新触发动画
要让反向动画平滑播放,你需要在切换类的时候让浏览器感知到动画属性的变化,从而触发新的动画。这里有个可靠的实现方式:
1. 定义初始和反向动画的CSS
/* 初始动画关键帧 */ @keyframes slide-in { from { transform: translateX(-100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } /* 初始动画类:动画完成后停在结束状态 */ .animate-in { animation: slide-in 1s ease-out forwards; } /* 反向动画类:复用同一个关键帧,方向设为reverse,完成后停在初始状态 */ .animate-out { animation: slide-in 1s ease-out reverse forwards; }
2. 用JavaScript监听动画结束并切换类
我们需要监听初始动画的animationend事件,通过"移除初始类→强制重绘→添加反向类"的流程触发动画:
const targetElement = document.querySelector('.your-target-element'); // 监听初始动画结束事件 targetElement.addEventListener('animationend', () => { // 移除初始动画类 targetElement.classList.remove('animate-in'); // 强制浏览器重绘:读取offsetWidth会触发重排,让浏览器感知到样式变化 void targetElement.offsetWidth; // 添加反向动画类,此时浏览器会重新执行动画 targetElement.classList.add('animate-out'); });
关键细节解释
void targetElement.offsetWidth:这一步是核心,它强制浏览器立即计算元素宽度,触发重排重绘,让浏览器意识到动画属性已经变化,必须重新执行动画,而不是直接跳转到最终状态。animation-fill-mode: forwards:确保动画结束后元素停在动画的最后一帧(反向动画的最后一帧就是原动画的初始状态)。
这样操作后,初始动画完成后,元素就会平滑地反向播放动画回到初始状态啦!
内容的提问来源于stack exchange,提问作者user13286
相关产品推荐
相关产品推荐

