transition适用于两个明确状态间的简单过渡,需定义起始值且依赖状态触发;animation则通过@keyframes定义多关键帧序列,支持循环、暂停及精细缓动控制。
当元素在 :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); }@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; }这是最常被问到的问题,根本原因往往不在语法,而在 CSS 层级或属性可动画性。
display、z-index、font-family 等不可动画,改用 visibility + opacity 组合:hover 写 color: red,但默认状态没声明 color(继承自父级),浏览器可能无法解析差值transition 属性实际生效且未被 !important 或更高权重规则屏蔽当需要「鼠标移入→淡入+上浮+旋转→停留2秒→缩小消失」这类多阶段行为时,强行用多个 class 切换配 transition 会失控:时间难对齐、状态难管理、取消动画极麻烦。
此时应直接用 animation 配合 animation-play-state: paused/running 控制,或用 JavaScript 调用 element.animate() API 实现动态参数调节。CSS transition 的设计初衷就是「状态间平滑衔接」,不是「编排时间线」。
真正容易被忽略的细节是:transition 的 timing function(如 cubic-bezier)作用于整个属性变化过程,而 animation 的每个关键帧都能单独指定 ease-in-out 类型 —— 这
让缓动控制更精细,但也更容易写出不自然的节奏。