animation-fill-mode: forwards 能保留动画最后一帧样式,但需配合显式定义的100%或to关键帧,且终态属性必须完整写出,否则会因缺值、覆盖或简写遗漏而失效。

animation-fill-mode: forwards 是唯一能真正保留最后一帧样式的做法,不加它,动画一停就跳回原始样式——这不是 bug,是 CSS 规范默认行为。
为什么写了 forwards 还是闪回?
根本原因不是属性写错了,而是浏览器没拿到“可保留的终值”:
-
@keyframes里漏了100%或to块:只写了0%和50%,浏览器会用元素原始transform补全终态,forwards锁住的就是这个错的值 - 被更高优先级样式覆盖:
style="opacity: 1"、带!important的类、或后续 CSS 规则(如.hidden { opacity: 0; })都会直接压过forwards保持的值 -
animation简写中没显式含forwards:只写animation: fadeIn 0.3s ease;,animation-fill-mode会被强制重置为none -
transform等复合属性没写全:比如动画中只在to里写了translateX(100px),但初始有scale(0.8),结束时scale就归零,导致视觉错乱
forwards 必须和 100% 关键帧配合才生效
forwards 不推测、不补全、不继承,它只忠实地锁住你明确写在 100% 或 to 里的那几行样式:
@keyframes slideIn {
from { transform: scale(0.8) rotate(-5deg); }
to { transform: translateX(100px) scale(0.8) rotate(-5deg); }
}
上面这段才是正确的——所有你想保留的 transform 属性都得在 to 中显式写出。同理,filter、opacity、color 等只要想保留,就必须出现在 100% 中。
立即学习“前端免费学习笔记(深入)”;
简写 vs 单独声明:顺序和覆盖关系极容易出错
两种写法都可行,但陷阱密集:
- 简写必须包含
forwards:animation: slideIn 0.4s ease forwards;(注意分号前有空格) - 分开写时,
animation-fill-mode: forwards;必须和animation在同一选择器下,且后面不能出现animation-fill-mode: none;这类重置 - 旧版 WebView(如 Android 4.4 内置浏览器)不支持
forwards,需加-webkit-animation-fill-mode: forwards;
最常被忽略的一点:forwards 只影响动画“结束后”的状态,对 animation-delay 阶段完全无效;如果还希望延迟期间就显示起始帧,得额外配 backwards 或直接上 both,而不是以为 forwards 能一揽子解决前后状态。


















