先记住这个答案
transition 是「属性值变了就过渡一下」,只做 A 到 B 的平滑切换,必须有触发条件。animation 是「按剧本演」,用 @keyframes 定义多个节点,可以自动播放、无限循环、正反交替。判断标准很简单:只有两个状态并且需要用户触发,用 transition;其它情况用 animation。
- 过渡需触发,动画可自播
transition只有起止两态animation支持多帧、循环、暂停- 按钮 hover 效果用
transition最合适
按钮 hover 效果:transition 的典型场景
鼠标移入时按钮放大并变色,移开时恢复。这就是最经典的两态切换,用 transition 三行就能搞定。
.btn {
background: #1677ff;
transform: scale(1);
transition: transform 0.2s ease, background 0.2s ease;
}
.btn:hover {
background: #4096ff;
transform: scale(1.05);
}不需要写 @keyframes,不需要指定播放次数,hover 进去自动正向过渡,hover 出来自动反向过渡。代码量少,意图清晰。
加载动画:animation 的典型场景
一个旋转的 loading 图标,页面打开就要转,一直转到数据加载完。这种不需要用户触发、无限循环的动画,只能用 animation。
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.loading {
animation: spin 1s linear infinite;
}transition 做不了这件事,因为没有「从什么值变到什么值」的触发点。animation 的 infinite 关键字让它永远循环,linear 保证匀速旋转不会一顿一顿的。
判断选哪个的三个问题
遇到一个动画需求,问自己三个问题。第一:有没有明确的触发条件?没有就用 animation。第二:是不是只有起止两个状态?不是就用 animation。第三:需不需要循环或暂停?需要就用 animation。三个问题都指向 transition 的话,用 transition 更简单。
比如一个通知横幅从顶部滑入、停留 3 秒、再滑出。这里有三个阶段(滑入、停留、滑出),transition 做不了「中间停一下」这种效果,要用 @keyframes 把百分比拆开。
还有一种情况:需要动画一进页面就播放一次(不循环)。比如页面加载时内容从下方淡入。这时候虽然只有两态,但没有触发条件,也要用 animation,设 animation-fill-mode: forwards 让它停在最后一帧。
容易答错的地方
- 以为
transition不能用 JavaScript 触发 transition的触发条件不局限于 CSS 伪类。JavaScript 修改classList或直接改style,导致计算值变化,一样会触发过渡。所以「JS 控制的动画就该用 animation」这个说法不对。- 以为
animation性能更差 - 两者的渲染管线一样,性能差异取决于你动了什么属性,不取决于用的是
transition还是animation。transform和opacity走 GPU 合成层,不管用哪种写法都很快。改width和height触发回流,不管用哪种写法都慢。
面试官还会怎么问?
两者可以同时用在一个元素上吗?
可以。比如一个图标平时用 animation 做呼吸灯效果(无限循环发光),hover 时用 transition 放大。两者互不干扰,各自控制不同的属性就行。如果控制了同一个属性,animation 的优先级更高。
Web Animations API 是什么定位?
它是 JavaScript 版本的 animation,提供了 CSS animation 做不到的精确控制,比如动态修改时长、跳到某一帧、串联多段动画。适合交互驱动的复杂动画,比如手势跟随、滚动联动。
transition 能做弹性效果吗?
能。用 cubic-bezier() 把 y 值设成大于 1 的数,动画末尾会冲过目标值再弹回来。但只能弹一下。如果要多次弹跳,就需要 @keyframes 手动写多个关键帧了。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。