animation-fill-mode: forwards 是让动画结束后保持终态的必要声明,因默认值为 none 会导致闪回;常见失效原因包括 @keyframes 缺 100%、高优先级样式覆盖、animation 简写未包含 forwards 或 iteration-count 设置不当。

animation-fill-mode: forwards 为什么必须显式写
动画结束后闪回原始状态,不是你写错了 @keyframes,而是浏览器默认行为:animation-fill-mode 的初始值就是 none。这意味着动画只在播放中生效,一停就撤掉所有关键帧里声明的样式——比如 opacity、transform 全部归零或还原到元素原始值。
加 forwards 不是“优化”,而是让动画真正落地的必要条件。不写它,100% 帧再完整也没用,浏览器压根不会保留。
写了 forwards 却还闪回?先查这三处
常见失效原因几乎都集中在这几个点:
-
@keyframes里漏了100%或to块:比如只写了0%和50%,浏览器会用元素初始transform补全终态,forwards锁住的就是这个“错的终值” - 被更高优先级样式覆盖:内联样式
style="opacity: 0"、带!important的类、或后续 CSS 规则(如.disabled { opacity: 0; })都会直接压过forwards保持的值 -
animation-iteration-count没设为1:如果用了infinite或没声明,默认是1,但若配合animation-direction: alternate,动画结束时可能停在反向最后一帧(即0%),看起来像回退了
animation 简写里漏掉 forwards 是高频翻车点
很多人只写 animation: fadeIn 0.3s ease;,以为 forwards 可以靠单独声明补上。但实际中,animation 简写会**重置所有未显式写出的子属性**,包括把 animation-fill-mode 强制设回 none。
正确写法只有两种:
- 直接写进简写:
animation: fadeIn 0.3s ease forwards;(注意分号前有空格) - 分开写,且确保
animation-fill-mode: forwards;和animation在同一选择器下,且没有被后续规则覆盖
另外,transform 是复合属性,动画中只写 translateX(100px),不代表它会保留原有 scale 或 rotate;forwards 只保持你明确定义的部分。
JS 触发动画时最容易忽略的时机问题
用 JS 动态添加动画 class 后立刻移除、或在 animationend 事件里马上读取 getComputedStyle,都可能导致 forwards 效果“看不见”:
- 刚加 class 就 remove,动画根本没走到“结束”,
forwards永远不触发 -
animationend触发时,渲染可能尚未完成,getComputedStyle(el).transform仍返回中间值;建议用requestAnimationFrame延迟一帧再读 - 用
el.style.animation = 'none'强制终止,会立刻丢弃forwards效果,元素退回到内联样式或层叠值
最稳的方式是:确保 class 添加后不干预,等动画自然播完;需要 JS 控制终态时,不如在 animationend 里直接写 el.style.transform = 'translateX(100px)'; 固化。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











