必须显式设置 animation-fill-mode: forwards,否则动画结束即恢复原始样式;常见失效原因包括 keyframes 缺 100%/to、动画未真正结束、被高优先级样式覆盖、direction/iteration-count 不匹配、未与 animation 同时声明、js 未同步设置、终帧属性未全部显式声明,以及响应式重排导致视觉偏移。

必须显式设置 animation-fill-mode: forwards,否则动画一结束就撤样式——这不是 bug,是 CSS 规范的默认行为。
为什么写了 forwards 还是闪回
根本不是属性写错了,而是浏览器没拿到“可保持的终值”。常见原因包括:
- @keyframes 里漏了
100%或to块:比如只写了0%和50%,浏览器会用元素原始transform补全终态,forwards锁住的就是这个错误值 - 动画根本没“结束”:设置了
animation-iteration-count: infinite,或被animation-play-state: paused拦在中途,forwards不触发 - 被更高优先级样式覆盖:内联样式如
style="opacity: 0"、带!important的类、或后续 CSS 规则(如.disabled { opacity: 0; })直接压过forwards保持的值 - 用了
animation-direction: alternate却没配animation-iteration-count: 1,动画播完停在反向最后一帧(即0%),看起来像回退
animation-fill-mode 必须和 animation 同时生效
它不是独立开关,而是依附于正在运行的动画。单独写 animation-fill-mode: forwards 但没配 animation,或写在不同选择器下,等于没写。
- 推荐直接简写:
animation: slideIn 0.4s ease forwards;——注意分号前有空格,部分浏览器解析敏感 - 如果分开写,确保
animation-fill-mode: forwards;和animation在同一选择器、同一权重下,且后面没出现animation-fill-mode: none;之类重置 - JS 动态设置时,别只改
element.style.animation,记得同步设element.style.animationFillMode = 'forwards'
关键帧里必须显式写出 100% 的所有目标属性
forwards 不会补全、不继承、不推测。它只保留你在 100% 或 to 中**明确声明**的属性值。
- 元素原本有
transform: scale(0.9) rotate(2deg),动画只写了to { transform: translateX(100px); },那结束时scale和rotate就归none - 正确写法是:
to { transform: translateX(100px) scale(0.9) rotate(2deg); } - 同理,
filter、opacity、color等只要你想保留,就必须在100%中全部写出 - 移动端建议统一用
100%而非to,部分老旧 Android WebView 对to解析不稳定
最容易忽略的一点:animation-fill-mode: forwards 只维持动画结束那一刻的计算值;之后若父容器尺寸变化、媒体查询切换或视口滚动导致重排,已“定格”的样式仍可能视觉偏移——这时候问题已不在 forwards,而在响应式上下文本身。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











