transition 与 animation 不能共用同一属性,因 CSS 层叠规则只保留最后声明值,且 animation 运行后会接管属性控制权,使 transition 插值逻辑失效;animation-fill-mode: forwards 更会导致过渡丢失起始值。

transition 和 animation 为什么不能共用同一属性
因为 CSS 层叠规则规定:同一选择器中,对同一属性的多个声明,只保留最后一个生效值。transition 和 animation 都会接管目标属性(比如 transform 或 opacity)的控制权;一旦 animation 开始运行,浏览器就认为该属性“已由动画管理”,transition 的插值逻辑直接被跳过——不是 bug,是规范行为。
animation-fill-mode: forwards 是最常被忽略的冲突源头
当 animation-fill-mode 设为 forwards(或 both),动画结束后元素会「锁死」在最后一帧的属性值上。此时你再通过 hover 或 class 切换去改同一个属性,transition 就找不到「起始值」——它看到的是动画留下的终态,而不是你写的初始 CSS 值,结果就是变化瞬间完成、毫无过渡。
- 典型表现:
.box { animation: slideIn 1s forwards; transition: transform 0.3s; }+:hover { transform: rotate(180deg); }→ hover 时旋转不缓动,直接跳转 - 验证方法:删掉
forwards,或临时设为none,hover 过渡立刻恢复 - 注意:
backwards同样危险——它会让动画未开始前就提前应用from值,覆盖你原本的初始状态
多个 transition 声明互相覆盖导致“部分失效”
写成两行 transition 不等于叠加效果,而是后者完全替代前者:
div {
transition: width 0.3s;
transition: height 0.4s; /* ← width 的过渡已丢失 */
}正确做法是合并为单条声明:
立即学习“前端免费学习笔记(深入)”;
div {
transition: width 0.3s, height 0.4s, opacity 0.2s;
}- 避免用
transition: all 0.3s,它会过渡所有可变属性(包括你没意识到的z-index、box-shadow),增加意外抖动风险 - 硬件加速属性优先:只对
transform、opacity做 transition/animation;避开width、height、top等触发重排的属性
想共存?必须严格隔离作用域
唯一安全的共存方式,是让 transition 和 animation 完全不碰同一个属性:
-
transition控制交互态:比如opacity、transform: scale()的 hover 进出 -
animation负责独立动效:比如transform: rotate()的无限旋转、background-position的滚动背景 - 实在要动同一属性(如都用
transform),得套一层 DOM:外层用transition控制位移,内层用animation控制旋转——物理隔离,互不干扰
真正难处理的从来不是语法,而是动画结束后状态是否“干净”:只要 animation 留下残留值(尤其靠 forwards 锁定的),transition 就永远找不到起点。


















