You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CSS Keyframe动画切换异常:复用同名关键帧为何失效?

问题描述

有一个矩形元素,点击按钮切换animation-in和animation-out类来实现淡入淡出的缩放动画。原本使用两个内容完全一致、仅名称不同的关键帧(scale-easeInOutBounce和scale-easeInOutBounce-out)时,动画运行正常;但将.animation-out的animation-name改为和.animation-in相同的scale-easeInOutBounce后,动画完全失效,点击按钮时元素直接跳变状态,没有过渡动画。该问题在Windows 11的Chrome浏览器中可复现。

失效代码如下:

<!DOCTYPE html>
<html>
<head>
    <title>Rectangle Animation</title>
    <style>
        #myRectangle {
            width: 100px;
            height: 150px;
            background-color: green;
            margin: 20px;
            transform: scale(0);
        }
        .animation-out {
            animation-duration: 4s;
            animation-timing-function: ease;
            animation-delay: 0s;
            animation-iteration-count: 1;
            animation-direction: normal;
            animation-fill-mode: forwards;
            animation-play-state: running;
            animation-name: scale-easeInOutBounce;
            animation-timeline: auto;
            animation-range-start: normal;
            animation-range-end: normal;
        }
        .animation-in {
            animation-duration: 4s;
            animation-timing-function: ease;
            animation-delay: 0s;
            animation-iteration-count: 1;
            animation-direction: reverse;
            animation-fill-mode: forwards;
            animation-play-state: running;
            animation-name: scale-easeInOutBounce;
            animation-timeline: auto;
            animation-range-start: normal;
            animation-range-end: normal;
        }
        @keyframes scale-easeInOutBounce {
            0% { transform: scale(1); }
            2% { transform: scale(0.99); }
            4% { transform: scale(1); }
            10% { transform: scale(0.97); }
            14% { transform: scale(0.99); }
            22% { transform: scale(0.88); }
            32% { transform: scale(0.99); }
            42% { transform: scale(0.6); }
            50% { transform: scale(0.5); }
            58% { transform: scale(0.4); }
            68% { transform: scale(0.01); }
            78% { transform: scale(0.12); }
            86% { transform: scale(0.01); }
            90% { transform: scale(0.03); }
            96% { transform: scale(0); }
            98% { transform: scale(0.01); }
            100% { transform: scale(0); }
        }
    </style>
</head>
<body>
<div id="myRectangle"></div>
<button id="toggleButton">Toggle Animation</button>
<script>
    document.getElementById('toggleButton').addEventListener('click', function() {
        var rectangle = document.getElementById('myRectangle');
        if (rectangle.classList.contains('animation-in')) {
            rectangle.classList.remove('animation-in');
            rectangle.classList.add('animation-out');
        } else {
            rectangle.classList.remove('animation-out');
            rectangle.classList.add('animation-in');
        }
    });
</script>
</body>
</html>
原因分析

核心问题在于CSS动画的状态复用机制:

  • 当元素应用过某个名称的动画并完成后,浏览器会保留该动画的状态(标记为“已完成”)。
  • 后续如果仅修改该动画的其他属性(如animation-direction)但保持animation-name不变,浏览器不会重新触发动画,而是直接应用新属性对应的最终状态,跳过过渡过程。
  • 原来使用不同关键帧名称时,每次切换类都是给元素应用一个全新的动画名称,浏览器会重新初始化并执行动画,因此能正常显示过渡效果;改成同一名称后,切换类时动画名称未变,浏览器认为无需重新执行动画,导致动画失效。
解决方案

要解决这个问题,需要强制浏览器重新初始化动画,常用方法是在切换类时先移除所有动画类,让浏览器完成重绘后再添加新类:

修改JavaScript代码如下:

document.getElementById('toggleButton').addEventListener('click', function() {
    var rectangle = document.getElementById('myRectangle');
    const hasInClass = rectangle.classList.contains('animation-in');
    // 先移除所有动画类
    rectangle.classList.remove('animation-in', 'animation-out');
    // 利用setTimeout让浏览器完成重绘后再添加新类
    setTimeout(() => {
        if (hasInClass) {
            rectangle.classList.add('animation-out');
        } else {
            rectangle.classList.add('animation-in');
        }
    }, 0);
});

这样每次切换时,元素会先回到无动画的初始状态,再应用新的动画类,浏览器会重新触发动画,恢复正常的过渡效果。


内容的提问来源于stack exchange,提问作者GrumpyDog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 06:12:06