transition适用于两个明确状态间的简单过渡,需定义起始值且依赖状态触发;animation则通过@keyframes定义多关键帧序列,支持循环、暂停及精细缓动控制。

transition 适合状态切换时的简单过渡
当元素在 :hover、:focus、class 切换等「两个明确状态之间」变化时,transition 是最直接的选择。它不描述过程,只声明「从 A 变到 B 时,用什么方式变」。
常见错误是给未定义初始状态的属性加 transition,比如只在 :hover 里写 transform: scale(1.2),但没在默认状态定义 transform: scale(1) —— 这会导致过渡失效,因为浏览器无法计算起始值。
-
transition必须配合可触发的状态变化(如 class 切换、伪类激活),不能独立运行 - 只能定义起始和结束两个关键帧,不支持中间状态控制
- 单次触发:默认只在状态进入时生效;若要进出都有过渡,需在默认状态和目标状态都写相同
transition声明 - 简写示例:
button { transition: background-color 0.3s ease, transform 0.2s cubic-bezier(0.2, 0.8, 0.4, 1); }
animation 需要显式定义关键帧序列
@keyframes 是 animation 的核心,必须先定义动画行为,再通过 animation 属性挂载到元素上。它不依赖状态切换,可以自动播放、循环、暂停,也能精确控制多个中间节点。
容易忽略的是:如果 animation-fill-mode 没设为 forwards,动画结束后元素会“弹回”初始样式,导致视觉断层 —— 尤其在 hover 触发的动画中很常见。
立即学习“前端免费学习笔记(深入)”;
-
@keyframes中的0%和100%不等价于 transition 的起/终点:它们是时间轴上的绝对位置,可自由添加25%、60%等中间帧 -
animation支持iteration-count: infinite、direction: alternate等控制逻辑,transition完全不支持 - 性能敏感场景慎用
animation驱动width/height或left/top:会频繁触发 layout;优先用transform和opacity - 简写示例:
@keyframes slideIn { 0% { opacity: 0; transform: translateX(-20px); } 100% { opacity: 1; transform: translateX(0); } } .element { animation: slideIn 0.4s ease-out forwards; }
hover 触发 transition 却没反应?检查这三点
这是最常被问到的问题,根本原因往往不在语法,而在 CSS 层级或属性可动画性。
- 目标属性是否支持过渡?
display、z-index、font-family等不可动画,改用visibility+opacity组合 - 是否遗漏了初始值?例如只在
:hover写color: red,但默认状态没声明color(继承自父级),浏览器可能无法解析差值 - 是否存在更高级别的选择器覆盖?用浏览器开发者工具检查 computed 样式,确认
transition属性实际生效且未被!important或更高权重规则屏蔽
复杂交互动画别硬套 transition
当需要「鼠标移入→淡入+上浮+旋转→停留2秒→缩小消失」这类多阶段行为时,强行用多个 class 切换配 transition 会失控:时间难对齐、状态难管理、取消动画极麻烦。
此时应直接用 animation 配合 animation-play-state: paused/running 控制,或用 JavaScript 调用 element.animate() API 实现动态参数调节。CSS transition 的设计初衷就是「状态间平滑衔接」,不是「编排时间线」。
真正容易被忽略的细节是:transition 的 timing function(如 cubic-bezier)作用于整个属性变化过程,而 animation 的每个关键帧都能单独指定 ease-in-out 类型 —— 这让缓动控制更精细,但也更容易写出不自然的节奏。










