CSS3 Animation 完整教程
CSS3 动画是现代网页设计中不可或缺的一部分,它能让页面元素生动起来,提供流畅的用户体验,而无需依赖 JavaScript,本教程将带你从零开始,一步步掌握 CSS 动画的精髓。

第一部分:核心概念 - Animation vs. Transition
在深入 animation 之前,我们先理解它与 transition 的区别,这是非常重要的。
| 特性 | transition (过渡) |
animation (动画) |
|---|---|---|
| 触发方式 | 需要用户交互(如 hover)或通过 JS 改变样式属性时触发。 |
可以自动播放,无需用户交互。 |
| 关键帧 | 只有“开始”和“结束”两个状态。 | 可以定义多个关键帧,控制动画的任意阶段。 |
| 控制能力 | 控制较少,主要控制持续时间、延迟、曲线等。 | 控制能力极强,可以暂停、反向、播放次数等。 |
| 语法 | 简单,直接在属性上定义。 | 需要先定义 @keyframes 规则,然后在元素上应用。 |
简单总结:
- Transition:适合简单的状态变化,比如鼠标悬停时按钮颜色的渐变。
- Animation:适合复杂、多步骤、可重复播放的动画,比如一个加载图标、一个飞入的卡片等。
第二部分:@keyframes - 动画的蓝图
@keyframes 是定义动画的核心,它像一个剧本,规定了动画在不同时间点(关键帧)的样式。
基本语法
@keyframes animationName {
0% {
/* 动画开始时的样式 */
}
50% {
/* 动画进行到一半时的样式 */
}
100% {
/* 动画结束时的样式 */
}
}
animationName: 给你的动画起一个名字,方便后面引用。0%,50%,100%: 这些是“关键帧选择器”,也叫“动画点”,你也可以使用from(等同于0%) 和to(等同于100%)。- 大括号 内部是 CSS 属性,定义了元素在该时刻的外观。
示例:一个简单的移动动画
让我们创建一个方块从左边移动到右边的动画。

HTML:
<div class="box"></div>
CSS:
.box {
width: 100px;
height: 100px;
background-color: steelblue;
/* 先让元素静止在起始位置 */
/* position: relative; */ /* 如果你想用 relative/absolute 来移动 */
}
/* 定义动画的“剧本” */
@keyframes moveRight {
0% {
/* 初始状态:在左侧 */
transform: translateX(0);
}
100% {
/* 结束状态:向右移动 300px */
transform: translateX(300px);
}
}
动画的“剧本”已经写好了,但还没有“演员”来表演,我们需要将这个动画应用到 .box 元素上。
第三部分:动画属性 - 让动画“活”起来
我们将使用一组 animation-* 属性来控制动画的播放方式、时间、次数等。

核心动画属性
animation-name: 指定要应用的@keyframes的名称。animation-duration: 动画完成一次所需的时间,单位是秒(s)或毫秒(ms)。默认为 0,所以如果不设置,你将看不到任何动画。animation-timing-function: 动画的速度曲线,它决定了动画播放的节奏。ease: 慢 -> 快 -> 慢 (默认)linear: 匀速ease-in: 慢 -> 快ease-out: 快 -> 慢ease-in-out: 慢 -> 快 -> 慢 (比ease更明显)cubic-bezier(): 自定义贝塞尔曲线,高级技巧。
animation-delay: 动画开始前的等待时间,单位是s或ms,可以是负数,表示动画已经开始,并跳过了指定的时间。animation-iteration-count: 动画的播放次数。infinite: 无限循环播放。- 数字:
2(播放两次)。
animation-direction: 动画的播放方向。normal: 正常方向 (默认,0% -> 100%)。reverse: 反向播放 (100% -> 0%)。alternate: 交替播放,第一轮正常,第二轮反向,如此反复。alternate-reverse: 交替反向播放,第一轮反向,第二轮正常,如此反复。
animation-fill-mode: 动画结束后元素的样式。none: 默认值,动画结束后回到原始状态。forwards: 动画结束后,元素停留在最后一帧(100%)的样式。backwards: 动画开始前,元素会立即应用第一帧(0%)的样式,并保持animation-delay设置的时间。both: 同时应用forwards和backwards的效果。
简写属性 animation
为了方便,CSS 提供了一个简写属性 animation,可以一次性设置上述所有(除 animation-fill-mode 外,但通常也包含)。
语法:
animation: name duration timing-function delay iteration-count direction fill-mode;
注意: 简写属性中,
duration和timing-function如果只写一个,浏览器会根据位置判断,但为了清晰,建议都写上。
第四部分:实战演练
让我们回到之前的 .box,用简写属性让它动起来。
HTML:
<div class="box"></div>
CSS:
.box {
width: 100px;
height: 100px;
background-color: steelblue;
/* 一次性定义所有动画属性 */
animation: moveRight 2s ease-in-out 1s infinite alternate;
}
@keyframes moveRight {
0% {
transform: translateX(0);
background-color: steelblue;
}
100% {
transform: translateX(300px);
background-color: tomato;
}
}
代码解析:
moveRight: 使用名为moveRight的动画。2s: 动画持续 2 秒。ease-in-out: 先慢后快再慢。1s: 延迟 1 秒后开始。infinite: 无限循环。alternate: 每次循环后反向播放。
效果: 方块会在 1 秒后开始,用 2 秒的时间从左边滑到右边(同时颜色从钢蓝色变为番茄色),然后反向滑回,如此反复。
第五部分:高级技巧与实例
多个关键帧动画
你可以在一个 @keyframes 中定义多个关键帧,创建更复杂的路径。
示例:一个呼吸效果
@keyframes breathe {
0%, 100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.2);
opacity: 0.7;
}
}
.element {
width: 100px;
height: 100px;
background-color: rebeccapurple;
animation: breathe 2s ease-in-out infinite;
}
组合多个动画
一个元素可以同时应用多个动画,用逗号 分隔。
示例:一个同时旋转和缩放的加载图标
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.1); }
}
.loader {
width: 50px;
height: 50px;
border: 5px solid #f3f3f3;
border-top: 5px solid #3498db;
border-radius: 50%;
/* 同时应用旋转和脉冲动画 */
animation: rotate 1s linear infinite, pulse 1.5s ease-in-out infinite;
}
注意: 当多个动画作用于同一个属性(如
transform)时,后面的动画会覆盖前面的,上面的例子之所以能同时生效,是因为rotate和pulse修改的是transform的不同部分(旋转和缩放),浏览器会尝试合并它们,如果冲突,后面的会优先。
使用 JavaScript 控制
你可以通过 JavaScript 动态地添加或移除类名来控制动画的播放和暂停。
HTML:
<button id="playBtn">播放</button> <button id="pauseBtn">暂停</button> <div class="box" id="myBox"></div>
CSS:
.box {
width: 100px;
height: 100px;
background-color: orange;
/* 默认不应用动画 */
}
.box.playing {
animation: moveRight 2s linear forwards;
}
JavaScript:
const myBox = document.getElementById('myBox');
const playBtn = document.getElementById('playBtn');
const pauseBtn = document.getElementById('pauseBtn');
playBtn.addEventListener('click', () => {
myBox.style.animationPlayState = 'running'; // 如果动画被暂停,则恢复
myBox.classList.add('playing'); // 应用动画类
});
pauseBtn.addEventListener('click', () => {
myBox.style.animationPlayState = 'paused'; // 暂停动画
});
animation-play-state: 这是一个独立的属性,用于控制动画的播放状态 (running或paused),它非常适合在动画运行时动态暂停,而不是移除整个动画。
第六部分:性能优化与最佳实践
-
使用
transform和opacity:- 尽量对
transform(如translate,scale,rotate) 和opacity属性进行动画。 - 这些属性由合成器(compositor)线程处理,不会触发整个页面的重排和重绘,性能最好。
- 避免对
width,height,margin,padding,top,left等属性进行动画,因为它们会触发重排,性能开销大。
- 尽量对
-
利用
will-change:- 对于非常复杂的动画,你可以提前告知浏览器某个元素将会发生变化,让浏览器提前做好优化准备。
- 示例:
will-change: transform, opacity; - 警告: 不要滥用
will-change,只在确实需要且性能问题突出的元素上使用,过度使用会消耗大量内存。
-
硬件加速:
- 当你对
transform和opacity进行动画时,现代浏览器会自动开启硬件加速(使用 GPU 加速渲染)。 - 有时,为了强制开启硬件加速,可以给元素添加一个
transform: translateZ(0);或transform: translate3d(0, 0, 0);,但这通常不是必需的。
- 当你对
-
保持简单:
动画的目的是增强用户体验,而不是炫技,过于复杂或突兀的动画会分散用户注意力,造成困扰。
恭喜你!你已经完成了 CSS3 Animation 的学习,现在你应该能够:
- 理解
animation与transition的区别。 - 熟练使用
@keyframes定义多步骤动画。 - 掌握
animation简写属性及其所有子属性。 - 创建复杂的组合动画。
- 使用 JavaScript 动态控制动画。
- 遵循性能优化的最佳实践。
从现在开始,大胆地在你的项目中使用 CSS 动画,让你的网页充满活力和魅力!
