“闪回”不是 bug,是 animation-fill-mode 默认为 none 导致动画结束后样式重置;forwards 失效常见于 keyframes 缺 100%、样式被覆盖、alternate 循环、简写漏写或 transform 未写全。

动画结束后“闪回”不是 bug,是默认行为 —— animation-fill-mode 默认为 none,动画一停,所有关键帧样式立刻失效,元素退回到原始 CSS 状态。
animation-fill-mode: forwards 为什么没生效
写了 forwards 却还是闪回,大概率卡在这几个地方:
-
@keyframes里没写全最后一帧:比如只定义了0%和50%,漏掉100%,浏览器会用元素初始值“补”终态,forwards拿到的就是错的值 - 动画属性被覆盖:元素有
style="transform: none"或更高优先级规则(如!important)强行重置了transform、opacity等,forwards压不过它 -
animation-direction: alternate配合了多次循环:比如animation-iteration-count: 2,forwards会停在第 2 次反向播放的终点(即起始帧),看起来像“回去了” - 简写
animation里漏了forwards:只写了animation: slideIn 0.4s;,没加forwards,等价于显式写了animation-fill-mode: none
transform 动画结束后不保持位移的典型原因
transform 不像 opacity 那样独立,它是复合属性;动画中只写 transform: translateX(200px),不代表它会“叠加”原有 scale 或 rotate —— 结束后只会保留动画里声明的那部分,其余归 none。
解决办法只有两个:
- 在
@keyframes的100%帧里,把所有要保留的transform值一次性写全,例如:transform: translateX(200px) scale(1.2) rotate(5deg); - 如果原始状态本就有
transform,且不能改写动画,就别用transform做动画,改用left/top+position: relative,或用 JS 在动画结束时手动 setStyle
animation-fill-mode: both 和 forwards 的区别在哪
both = backwards + forwards,但它只在特定场景有用:
-
backwards生效的前提是设置了animation-delay:延迟期间,元素会提前应用0%关键帧样式(比如还没开始动就先移到起点) - 没设
delay时,both和forwards行为完全一致 - 如果动画本身没延迟,又写了
both,只是多打几个字,没额外收益,还可能误导后续维护者以为“有延迟逻辑”
真正容易被忽略的是:即使 forwards 生效,它也只维持动画结束那一刻的计算值;如果动画依赖视口尺寸、父容器变化或媒体查询,这些外部变动仍会触发重排,让“保持住的样式”看起来又变了 —— 这时候问题已不在 animation-fill-mode,而在响应式上下文本身。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











