transition适合用户触发的明确起止态交互,如按钮悬停、菜单展开、输入框聚焦、卡片上浮;需显式定义起始态和结束态,且不能与animation混用同一属性。

transition 适合什么交互场景
当你的动效只依赖用户操作(比如 :hover、:focus、JS 切换 class)且只有明确的「起始态 → 结束态」时,transition 是更轻、更稳的选择。
常见可用场景包括:
- 按钮悬停变色或缩放(
background-color+transform: scale()) - 菜单展开/收起(用
max-height或opacity+transform) - 表单输入框获得焦点时边框高亮(
border-color+box-shadow) - 卡片鼠标移入上浮(
transform: translateY(-4px))
关键前提是:两个状态都得显式写出具体值。比如只在 :hover 里写 transform: scale(1.1),但默认状态没写 transform: scale(1),过渡就失效——浏览器没法算起始值。
animation 必须用在哪些地方
只要出现以下任一需求,transition 就无能为力,必须用 @keyframes + animation:
立即学习“前端免费学习笔记(深入)”;
- 需要循环播放(如
animation-iteration-count: infinite的 loading spinner) - 要求中间有多个停顿点(比如 0% → 25% → 50% → 100%,实现“弹跳+旋转+淡入”组合)
- 要控制播放方向(
animation-direction: alternate)、暂停(animation-play-state: paused)或倒播 - 动画需自动启动(页面加载即执行,不等用户 hover)
典型翻车点:用 animation 实现 hover 弹出菜单却忘了加 animation-fill-mode: forwards,结果动画一结束元素立刻回退到初始态,UI 断层;或者用 transition 硬凑三段位移,结果属性变更被合并,动画直接跳帧。
同一属性上混用 transition 和 animation 的风险
两者不能对同一 CSS 属性同时生效——后声明的会覆盖前一个。比如:
.box {
transition: transform 0.3s;
animation: slideIn 2s;
}
@keyframes slideIn {
to { transform: translateX(100px); }
}
这段代码中,transform 的过渡会被 animation 完全接管,transition 形同虚设。
安全做法是:
- 用
transition控制交互态(如 hover 进出) - 用
animation处理独立运行的动效(如背景粒子、心跳图标) - 若必须共存,确保它们作用于不同属性(例如
transition管opacity,animation管transform)
性能上,两者都优先用 transform 和 opacity;避免对 width、height、top 做过渡或动画,否则频繁触发 layout,卡顿明显。
容易被忽略的兼容性细节
现代浏览器支持都没问题,但老环境仍有坑:
- Android WebView(尤其 4.4 及更早)对
cubic-bezier()解析不准,建议 fallback 到ease或linear -
animation-fill-mode: forwards在 IE10–11 中支持,但部分旧版 UC 浏览器会忽略,需配合 JS 补充 class 固定终态 -
transition在 Safari 旧版本中对all的解析较宽松,但某些属性(如display)本就不支持过渡,写transition: all 0.3s反而掩盖问题
真正难的不是语法,而是判断「这个动效到底需不需要时间轴」——一旦开始想“第 30% 该干嘛”,你就该切到 @keyframes 了。


















