css-animation
CSS 动画的常见属性、使用方式,以及和过渡效果的选择边界。
[!info] related notes
css-animation
CSS 动画的核心是:让样式在一段时间内从一个状态变化到另一个状态。
一句话定义
如果只是“某个状态切到另一个状态”,优先想 transition;如果要定义更完整的关键帧过程,使用 animation。
先抓住两条主路
CSS 里“让东西动起来”最常见的是两类:
transitionanimation
但它们更像“播放机制”,真正变化的通常是具体属性,比如 transform、opacity、color、background-color。
所以更准确地说:
transition/animation决定怎么播放transform/opacity决定到底变什么
transition 和 animation 到底差在哪
transition
适合“从一个状态平滑过渡到另一个状态”。
典型场景:
- hover
- focus
- active
- class 切换
- 折叠展开
它依赖的是“状态变化”。如果没有前后两个状态,就不会自己播放。
animation
适合“主动播放一段预先定义好的动画过程”。
典型场景:
- 元素入场
- loading
- 无限循环旋转
- 呼吸灯
- 多关键帧节奏变化
它依赖的是 @keyframes,可以直接定义 0%、50%、100% 等多个阶段。
常用属性
| 属性 | 说明 | 示例值 |
|---|---|---|
animation-name | 指定要运用的关键帧名称 | slideIn |
animation-duration | 动画完成一个周期所需时间 | 1s 或 1000ms |
animation-timing-function | 动画的速度曲线 | linear, ease, ease-in, ease-out, cubic-bezier(0.1, 0.7, 1.0, 0.1) |
animation-delay | 动画开始前的延迟时间 | 2s |
animation-iteration-count | 动画播放次数 | 3, infinite |
animation-direction | 动画是否反向播放 | normal, reverse, alternate, alternate-reverse |
animation-fill-mode | 动画执行前后如何应用样式 | none, forwards, backwards, both |
animation-play-state | 动画运行或暂停 | running, paused |
最常见的题:hover 时变色 + 变圆 + 200ms
题目一般像这样:
- 一个
100 x 100的红色div - 鼠标移上去后变黑
- 同时变成圆形
- 动画时间
200ms
这类题其实更适合直接用 transition:
<div class="box"></div>
.box {
width: 100px;
height: 100px;
background: red;
border-radius: 0;
transition: background-color 200ms ease, border-radius 200ms ease;
}
.box:hover {
background: black;
border-radius: 50%;
}
为什么这里更推荐 transition
- 因为只有“初始态 -> hover 态”两个状态
- 不需要多段关键帧
- 写法更短,也更符合题目意图
什么时候该用 animation
当题目要求:
- 自动播放
- 无限循环
- 多阶段变化
- 精确控制 0%、50%、100% 等过程
这时再写 @keyframes:
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
.box {
animation: pulse 1s infinite;
}
一个更直观的对比
transition 更像补间
你只告诉浏览器:
从 A 状态变到 B 状态时,用一段时间平滑过去。
.card {
transition: transform 0.25s ease, opacity 0.25s ease;
}
.card:hover {
transform: translateY(-4px);
opacity: 0.92;
}
animation 更像时间轴剧本
你直接告诉浏览器:
第 0% 是什么样,第 50% 是什么样,第 100% 是什么样。
@keyframes bounce {
0% {
transform: translateY(0);
}
30% {
transform: translateY(-20px);
}
60% {
transform: translateY(0);
}
100% {
transform: translateY(-8px);
}
}
.ball {
animation: bounce 0.8s ease;
}
开发里怎么选
可以先问自己两个问题:
1. 这个效果是不是“状态切换触发”的
如果是,优先想 transition。
例如:
- hover 反馈
- 输入框聚焦
- 展开收起
- 通过 class 切换显隐
2. 这个效果是不是“自己播放的一段过程”
如果是,优先想 animation。
例如:
- 页面入场
- loading 旋转
- 循环闪烁
- 多阶段弹跳
transform 为什么在动画里这么常见
很多人会误以为 transform 本身就是动画类型,其实不是。
transform是被变化的属性transition/animation是让变化有时间过程的机制
最常做动画的 transform 包括:
translatescalerotate
例如:
.box {
transition: transform 0.3s ease;
}
.box:hover {
transform: scale(1.05);
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loader {
animation: spin 0.8s linear infinite;
}
显示隐藏为什么常配合 opacity
不是所有属性都适合做平滑动画。
opacity、transform这类属性通常可以自然插值display这类属性不是连续值,通常不能平滑过渡
所以做淡入淡出时,更常见的写法不是直接动画 display,而是:
.modal {
opacity: 0;
transform: scale(0.95);
transition: opacity 0.2s ease, transform 0.2s ease;
}
.modal.show {
opacity: 1;
transform: scale(1);
}
这也是为什么“显示隐藏”经常要联动 display-none-visibility-hidden-opacity-zero 一起理解。
timing function 在控制什么
不管是 transition 还是 animation,timing-function 控制的都是速度曲线,不是总时长。
常见直觉:
linear:匀速ease:默认,更柔和ease-in:前慢后快ease-out:前快后慢ease-in-out:两头慢,中间快
经验上:
- loading 旋转常用
linear - hover 反馈常用
ease或ease-out
两者能不能一起用
可以,而且很常见。
例如元素入场用 animation,hover 反馈再用 transition:
@keyframes fadeSlideIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.card {
animation: fadeSlideIn 0.6s ease forwards;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
}
性能上的保守规则
CSS 动画不等于一定高性能。
优先考虑这些属性:
transformopacity
更要谨慎这些属性:
widthheighttopleftmargin
因为它们更容易引发布局和重绘。要理解原因,可以回看 reflow-vs-repaint-interview-question 和 browser-rendering-process。
一句话记忆法
transition:状态变了,我帮你慢慢过渡animation:我自己定义一整段时间轴来播放
面试里一句话怎么答
如果只是 hover 切换颜色和圆角,我会优先用 transition;如果是多阶段、循环或更复杂的时间轴动画,我才会用 animation + keyframes。