animation-fill-mode 控制动画前后是否保留关键帧样式,默认 none 导致动画结束“弹回去”;forwards 最常用,可保留末帧样式,但需确保动画执行完、无样式覆盖、不与 transition 冲突。

animation-fill-mode 是什么,为什么动画一结束就“弹回去”
它控制 CSS 动画执行前、执行后是否保留关键帧样式。默认值是 none,所以动画一停,元素立刻恢复到动画前的状态——不是 bug,是设计如此。
常见错误现象:transform 或 opacity 动画结束后跳回初始值;hover 触发动画,鼠标移开后样式消失;用 @keyframes 移动位置,但动画完元素又“闪”回原处。
-
animation-fill-mode: forwards最常用:保留最后一帧的样式(即100%或to的声明) -
backwards会应用第一帧(0%或from),仅在animation-delay为负数时可见效果 -
both=forwards+backwards,慎用,容易和初始样式冲突
forwards 不生效?检查这三件事
写了 forwards 却没留住状态,大概率不是属性写错,而是被其他规则覆盖或条件不满足。
- 动画必须成功触发并执行完——如果
animation-duration是0s或animation-iteration-count设为0,forwards不起作用 - 目标属性不能被后续 CSS 覆盖,比如动画设置了
opacity: 0,但后面又有div { opacity: 1 },那forwards就被干掉了 - 避免和
transition混用:如果元素同时有transition和animation,且动画结束后的值与 transition 初始值不同,可能触发意外过渡,看起来像“没留住”
JS 控制动画时,fill-mode 和 getComputedStyle 的坑
用 JS 启停动画、读取最终样式时,animation-fill-mode 的行为会影响结果,尤其在动画刚结束的瞬间。
立即学习“前端免费学习笔记(深入)”;
-
getComputedStyle(el).opacity在动画播放中或刚结束时,可能返回中间值,而不是forwards承诺的终值——因为浏览器渲染尚未完成,建议加requestAnimationFrame延迟读取 - 用
el.style.animation = 'none'强制终止动画,会立即丢弃forwards效果,元素回归内联样式或层叠值 - 若用 JS 动态设置
animation,记得把animation-fill-mode一起设上,别只写在 CSS 里——CSS 规则可能被 JS 设置的animation值整体覆盖
兼容性与性能小提醒
animation-fill-mode 在所有现代浏览器都支持(包括 IE10+),但有两个实际限制得心里有数。
- 它只对由
@keyframes定义的 CSS 动画生效,对transition无效 - 启用
forwards不增加额外渲染负担,但若动画末帧触发了布局(如改height、top),仍会引发重排,和 fill-mode 本身无关 - 在 Safari 旧版本(≤14.1)中,
forwards对transform的某些组合(如scale+rotate同时存在)偶有渲染残留,可加transform: translateZ(0)强制硬件加速缓解
forwards 却没效果,其实问题往往不在这个属性本身,而在它所依赖的上下文是否干净——动画有没有真正跑完、样式有没有被覆盖、JS 有没有无意中重置了它。










