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

如何避免CSS动画随JS setInterval执行反复重启?

问题根源

你遇到的问题是因为每秒执行updateTimer时,都通过innerHTML替换了整个#timer容器的内容,这会销毁原来的子div元素并创建新的。每个新创建的div都会重新触发CSS动画,导致动画每秒重启一次。


解决方案

要让动画只执行一次,核心是保留原来的子div元素,只更新它们的内容而不是重新创建。下面提供两种可行的方案:

方案一:直接更新现有子div的内容

修改JS代码,不再替换#timer的innerHTML,而是获取已存在的子div并逐个更新内容:

function updateTimer(){
    const target = Date.parse("9 January 2023, 00:00:00");
    const today = new Date();
    const diff = target - today;
    
    let days = Math.floor(diff / (1000 * 60 * 60 * 24));
    let hours = Math.floor(diff / (1000 * 60 * 60));
    let mins = Math.floor(diff / (1000 * 60));
    let secs = Math.floor(diff / 1000);

    hours = hours - days * 24;
    const minutes = mins - hours * 60;
    const seconds = secs - mins * 60;
    
    // 获取已存在的子div元素
    const timerDivs = document.getElementById("timer").children;
    
    // 逐个更新内容,不重新创建div
    timerDivs[0].innerHTML = `${days}<span> Days</span>`;
    timerDivs[1].innerHTML = `${hours}<span> Hours</span>`;
    timerDivs[2].innerHTML = `${minutes}<span> Minutes</span>`;
    timerDivs[3].innerHTML = `${seconds}<span> Seconds</span>`;
}

// 立即执行一次,避免初始空白状态
updateTimer();
// 每秒更新倒计时
setInterval(updateTimer, 1000);

方案二:拆分数字与标签元素(更推荐)

调整HTML结构,为每个数字单独设置元素,仅更新数字的文本内容,完全不修改元素结构:
HTML修改为:

<div id="timer">
    <div><span class="num"></span><span class="label">Days</span></div>
    <div><span class="num"></span><span class="label">Hours</span></div>
    <div><span class="num"></span><span class="label">Minutes</span></div>
    <div><span class="num"></span><span class="label">Seconds</span></div>
</div>

对应的JS代码:

function updateTimer(){
    const target = Date.parse("9 January 2023, 00:00:00");
    const today = new Date();
    const diff = target - today;
    
    let days = Math.floor(diff / (1000 * 60 * 60 * 24));
    let hours = Math.floor(diff / (1000 * 60 * 60));
    let mins = Math.floor(diff / (1000 * 60));
    let secs = Math.floor(diff / 1000);

    hours = hours - days * 24;
    const minutes = mins - hours * 60;
    const seconds = secs - mins * 60;
    
    // 获取所有数字元素
    const numElements = document.querySelectorAll("#timer .num");
    
    // 仅更新文本内容
    numElements[0].textContent = days;
    numElements[1].textContent = hours;
    numElements[2].textContent = minutes;
    numElements[3].textContent = seconds;
}

updateTimer();
setInterval(updateTimer, 1000);

修正CSS动画错误

你把animation-delay写在了关键帧内部,这是无效的。应该将延迟属性放在元素的动画声明中:

@keyframes timerSlideUp{
    0%{
        opacity: 0;
    }
    100%{
        opacity: 1;
    }
}

#timer{
    color: white;
    padding: 20px;
    text-align: center;
}

#timer div{
    display: inline-block;
    min-width: 40px;
    padding: 15px;
    background: transparent;
    border-radius: 3px;
    border: 5px solid white;
    margin-top: 30%;
    margin-left: 5px;
    margin-right: 5px;
    text-align: center;
    font-size: 2em;
    font-weight: bold;
    /* 动画延迟5秒,持续5秒,保持结束状态 */
    animation: timerSlideUp 5s forwards 5s;
}

这样修改后,子div元素只会在页面加载时执行一次入场动画,后续倒计时更新不会再触发动画重启,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 18:55:30