CSS3 Animation 完整教程

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

css3 animation教程
(图片来源网络,侵删)

第一部分:核心概念 - 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 属性,定义了元素在该时刻的外观。

示例:一个简单的移动动画

让我们创建一个方块从左边移动到右边的动画。

css3 animation教程
(图片来源网络,侵删)

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-* 属性来控制动画的播放方式、时间、次数等。

css3 animation教程
(图片来源网络,侵删)

核心动画属性

  1. animation-name: 指定要应用的 @keyframes 的名称。
  2. animation-duration: 动画完成一次所需的时间,单位是秒(s)或毫秒(ms)。默认为 0,所以如果不设置,你将看不到任何动画。
  3. animation-timing-function: 动画的速度曲线,它决定了动画播放的节奏。
    • ease: 慢 -> 快 -> 慢 (默认)
    • linear: 匀速
    • ease-in: 慢 -> 快
    • ease-out: 快 -> 慢
    • ease-in-out: 慢 -> 快 -> 慢 (比 ease 更明显)
    • cubic-bezier(): 自定义贝塞尔曲线,高级技巧。
  4. animation-delay: 动画开始前的等待时间,单位是 sms,可以是负数,表示动画已经开始,并跳过了指定的时间。
  5. animation-iteration-count: 动画的播放次数。
    • infinite: 无限循环播放。
    • 数字:2 (播放两次)。
  6. animation-direction: 动画的播放方向。
    • normal: 正常方向 (默认,0% -> 100%)。
    • reverse: 反向播放 (100% -> 0%)。
    • alternate: 交替播放,第一轮正常,第二轮反向,如此反复。
    • alternate-reverse: 交替反向播放,第一轮反向,第二轮正常,如此反复。
  7. animation-fill-mode: 动画结束后元素的样式。
    • none: 默认值,动画结束后回到原始状态。
    • forwards: 动画结束后,元素停留在最后一帧(100%)的样式。
    • backwards: 动画开始前,元素会立即应用第一帧(0%)的样式,并保持 animation-delay 设置的时间。
    • both: 同时应用 forwardsbackwards 的效果。

简写属性 animation

为了方便,CSS 提供了一个简写属性 animation,可以一次性设置上述所有(除 animation-fill-mode 外,但通常也包含)。

语法:

animation: name duration timing-function delay iteration-count direction fill-mode;

注意: 简写属性中,durationtiming-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)时,后面的动画会覆盖前面的,上面的例子之所以能同时生效,是因为 rotatepulse 修改的是 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: 这是一个独立的属性,用于控制动画的播放状态 (runningpaused),它非常适合在动画运行时动态暂停,而不是移除整个动画。

第六部分:性能优化与最佳实践

  1. 使用 transformopacity

    • 尽量对 transform (如 translate, scale, rotate) 和 opacity 属性进行动画。
    • 这些属性由合成器(compositor)线程处理,不会触发整个页面的重排和重绘,性能最好。
    • 避免width, height, margin, padding, top, left 等属性进行动画,因为它们会触发重排,性能开销大。
  2. 利用 will-change

    • 对于非常复杂的动画,你可以提前告知浏览器某个元素将会发生变化,让浏览器提前做好优化准备。
    • 示例: will-change: transform, opacity;
    • 警告: 不要滥用 will-change,只在确实需要且性能问题突出的元素上使用,过度使用会消耗大量内存。
  3. 硬件加速

    • 当你对 transformopacity 进行动画时,现代浏览器会自动开启硬件加速(使用 GPU 加速渲染)。
    • 有时,为了强制开启硬件加速,可以给元素添加一个 transform: translateZ(0);transform: translate3d(0, 0, 0);,但这通常不是必需的。
  4. 保持简单

    动画的目的是增强用户体验,而不是炫技,过于复杂或突兀的动画会分散用户注意力,造成困扰。


恭喜你!你已经完成了 CSS3 Animation 的学习,现在你应该能够:

  • 理解 animationtransition 的区别。
  • 熟练使用 @keyframes 定义多步骤动画。
  • 掌握 animation 简写属性及其所有子属性。
  • 创建复杂的组合动画。
  • 使用 JavaScript 动态控制动画。
  • 遵循性能优化的最佳实践。

从现在开始,大胆地在你的项目中使用 CSS 动画,让你的网页充满活力和魅力!