CSS动画结束后如何保持最终状态?

来源:站长平台作者:孙悟空头衔:草根站长
导读:本期聚焦于孙悟空创作的《CSS动画结束后如何保持最终状态?》,敬请观看详情。明明在@keyframes里把最后一帧写成opacity:1,动画播完元素却又变回透明,这种情况在CSS动画中非常常见。根因是动画结束后浏览器不再把动画样式应用到元素上,元素会回到不带动画时的原始样式。要解决这个问题,最直接的方法是使用animation-fill-mode属性,并把取值设为forwards,这样最后一帧的样式会继续保留。除此之外,还可以把结束状态直接写到元素基础样式中,或者改用transition实现一次性过渡,甚至通过JavaScript监听animationend事件添加一个持久类名。本文通过示例对比这些方案的实现方式和适用场景,并提醒读者注意transform等复合属性的叠加问题、display属性的限制,以及动画简写中fill-mode的书写顺序,帮助你在实际项目中稳定地让动画停留在最终画面。

CSS动画默认在播放结束后会释放对元素样式的控制,元素重新回到没有动画时定义的样式。很多操作元素淡入、位移的交互场景,需要动画完成之后停在最后一帧,而不是跳回初始状态。这个需求可以用一个核心属性解决:animation-fill-mode

CSS动画结束后如何保持最终状态?

不过,真正写项目时只是加上forwards并不总能一次生效,尤其是涉及transformopacity等多个属性,或者多个动画同时作用时,还要理解基础样式、动画简写顺序和其他替代方案的差异。下面从原因、用法、替代方案和注意事项几个角度展开。

一、动画结束后为什么会跳回原样

CSS动画由@keyframes定义一组关键帧,浏览器在animation-duration规定的时间内依次计算每一帧的样式。动画运行期间,关键帧中的属性会覆盖元素的基础样式,但这种覆盖只发生在动画的持续时间内。一旦动画结束,浏览器会停止将关键帧样式应用于元素,元素的呈现就回到animation属性不存在时的状态。

举例来说,如果元素本身没有设置opacity,而动画从opacity:0过渡到opacity:1,动画结束后元素不会保留opacity:1,而是回到默认的opacity:1。这听起来刚好符合预期,但假如元素基础样式是opacity:0,动画只在中间阶段把它变为可见,结束后又会突然隐藏。很多淡入动画失败,就是因为结束状态没有同时落实到元素本身。

/* 元素基础样式是透明,动画结束后会跳回透明 */
.box {
  opacity: 0;
  animation: fadeIn 1s ease;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

这个例子中,动画播放期间元素逐渐显示,但结束后由于基础样式仍然生效,元素会立刻消失。要解决这个问题,就需要让最后一帧的样式继续作用于元素。

二、使用 animation-fill-mode: forwards 实现保持

animation-fill-mode控制动画执行前后是否将动画样式应用到元素上。它有四个取值:noneforwardsbackwardsboth。其中forwards表示动画结束后保留最后一个关键帧的样式,这正是让元素停留在最终状态的关键。

上面的例子只需要改一行:

.box {
  opacity: 0;
  animation: fadeIn 1s ease forwards;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

添加forwards后,动画结束时to帧中的opacity:1会继续保留。需要注意,forwards只作用于动画结束之后的状态,不会改变动画开始前的延迟阶段。如果希望动画在延迟期间就应用第一帧样式,可以使用backwards;如果同时需要延迟阶段应用第一帧、结束后保留最后一帧,则使用both

简写属性中的位置也值得留意。标准写法是animation: name duration timing-function delay iteration-count direction fill-mode play-state。因此forwards通常放在时间参数之后,例如animation: fadeIn 1s ease 0s 1 normal forwards。如果顺序写错,浏览器可能把forwards当作动画名称或其他参数,导致无效。

三、其他几种保持最终状态的方法

如果不想使用animation-fill-mode,也可以从基础样式入手。直接把动画结束时的目标值写在元素的普通样式中,这样即使动画结束,元素也不会产生视觉跳动。前面淡入的例子中,把.box的基础opacity改为1即可。这种方式适合结束状态与元素常规状态一致的场景,维护起来更直观,缺点是无法覆盖那些只在动画结束后才应该存在、平时并不需要的样式。

.box {
  opacity: 1;
  animation: fadeIn 1s ease;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

对于只有开始和结束两个状态的简单交互,使用transition配合类名切换也可以避免跳回问题。transition本身只描述属性变化过程,属性最终值始终来自元素当前样式,因此只要最终样式已经写在元素上,自然不会有“动画结束丢失”的困扰。

.box {
  opacity: 0;
  transition: opacity 1s ease;
}

.box.active {
  opacity: 1;
}

还可以借助JavaScript监听animationend事件,在动画结束后添加一个持久类名。此方案更灵活,可以在动画结束后继续执行其他逻辑,例如更新状态、移除动画类、避免重复触发等。

const box = document.querySelector('.box');

box.addEventListener('animationend', function () {
  box.classList.add('animation-done');
});
.box {
  opacity: 0;
  animation: fadeIn 1s ease;
}

.box.animation-done {
  opacity: 1;
  animation: none;
}

这段代码在动画结束后把opacity固定为1,同时移除动画,避免后续状态被再次触发。缺点是增加了一定脚本依赖,但可以处理更复杂的条件。

四、实际使用中的注意点

当动画属性包含transform时,forwards保留的最后一帧会覆盖元素原来的transform。如果元素同时需要承担其他位移或旋转,可能会出现位置偏移。例如基础样式设置了transform: translateX(20px),而动画的最后一帧是transform: translateX(0),动画结束后元素会停在translateX(0),不再是20px。因此要确保动画结束帧与元素后续状态的transform一致,或者把目标值完整地写在结束帧和基础样式中。

多个动画同时作用于同一个元素时,后声明的动画会覆盖前一个动画对同一属性的控制。要想让多个动画各自保持结束状态,可以在每个动画的简写中分别加上forwards,并且不要在两个动画中同时操作相同的CSS属性。如果确实需要叠加transform,建议把位移、缩放、旋转拆到不同层级的元素上,从结构上避免冲突。

另外,display属性无法在动画关键帧中平滑过渡,也不会通过forwards可靠地保持显示或隐藏状态。如果动画结束需要元素保持可见,最好使用opacityvisibility控制隐藏效果,而不是直接切换display:none。对于需要从页面中移除元素的场景,可以在动画结束后通过JavaScript再设置display,避免动画和布局相互干扰。

最后,animation-fill-mode: forwards兼容现代浏览器和较新的移动端环境。对于非常老旧的浏览器,可以结合基础样式降级,让元素即使没有保持动画帧也能正常显示。实际项目中优先采用基础样式与forwards配合的方式,既简单又稳定。

CSS动画animation-fill-modeforwards修改时间:2026-08-25 08:51:39

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。