CSS3 动画终极教程:从入门到精通

CSS3 动画让网页元素能够以平滑、优雅的方式动起来,无需复杂的 JavaScript,它主要由两部分组成:

animation css3教程
(图片来源网络,侵删)
  1. 过渡:用于实现元素状态(如颜色、位置、大小)的平滑变化。
  2. 动画:用于实现更复杂、多步骤、可控制的动画序列。

我们将从最简单的 transition 开始,逐步深入到功能强大的 @keyframes 动画。


第一部分:CSS 过渡 - 实现平滑的状态变化

过渡是 CSS3 动画的基础,它允许你为属性值的变化添加一个“缓动”效果。

核心概念

过渡效果由四个核心属性控制:

  • transition-property: 指定哪个 CSS 属性需要添加过渡效果(width, background-color, transform)。
  • transition-duration: 指定过渡效果持续的时间(5s, 1000ms)。
  • transition-timing-function: 指定过渡的速度曲线,控制动画的节奏感。
  • transition-delay: 指定过渡效果开始前的延迟时间。

为了方便,通常使用简写属性 transition

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

语法与示例

基本语法:

.element {
  /* 简写形式: property duration timing-function delay */
  transition: all 0.5s ease-in-out 0.2s;
  /* 或者分开写 */
  transition-property: width, background-color;
  transition-duration: 0.5s;
  transition-timing-function: ease-in-out;
  transition-delay: 0.2s;
}

示例:一个简单的悬停效果

HTML:

<button class="hover-btn">悬停我</button>

CSS:

animation css3教程
(图片来源网络,侵删)
.hover-btn {
  padding: 15px 30px;
  font-size: 16px;
  background-color: #3498db;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  /* 初始状态,定义过渡 */
  transition: background-color 0.3s ease, transform 0.3s ease;
}
/* 鼠标悬停时的目标状态 */
.hover-btn:hover {
  background-color: #e74c3c;
  transform: scale(1.05); /* 轻微放大 */
}

代码解析:

  1. .hover-btn 是元素的初始样式。
  2. transition 属性告诉浏览器:当 background-colortransform 这两个属性发生变化时,要用 3s 的时间,以 ease 的速度曲线来平滑过渡。
  3. 当鼠标移到 .hover-btn 上时(hover 伪类),它的 background-color 变成了红色,transform 变成了 scale(1.05)
  4. 因为之前定义了 transition,所以这个变化不是瞬间完成的,而是持续了 3s,从而产生了平滑的动画效果。

常用的 transition-timing-function

  • ease: 默认值,慢速开始,然后加快,最后变慢。
  • linear: 匀速,从头到尾速度相同。
  • ease-in: 慢速开始。
  • ease-out: 慢速结束。
  • ease-in-out: 慢速开始和结束,类似 ease 但更明显。
  • cubic-bezier(n, n, n, n): 自定义贝塞尔曲线,可以创建非常独特的速度节奏。

第二部分:CSS 动画 - 创建复杂的多步动画

当简单的过渡无法满足需求时(想让元素弹跳、旋转多次、沿着复杂路径移动),就需要使用 @keyframes 动画。

核心概念

CSS 动画主要由两部分组成:

  • @keyframes 规则:定义动画的各个阶段(关键帧),你告诉浏览器在动画的 0%、25%、50%、75%、100% 等时间点,元素应该是什么样子。
  • 动画属性:将 @keyframes 应用到 HTML 元素上,并控制其行为。

@keyframes 规则

@keyframes 的名字可以自定义,用于后续引用。

@keyframes slideIn {
  /* 动画开始时的状态 */
  0% {
    transform: translateX(-100%);
    opacity: 0;
  }
  /* 动画 50% 时的状态 */
  50% {
    opacity: 1;
  }
  /* 动画结束时的状态 */
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}

动画属性

将定义好的动画应用到元素上:

  • animation-name: 指定要引用的 @keyframes 的名字。
  • animation-duration: 指定动画完成一次所需的时间。
  • animation-timing-function: 指定动画的速度曲线。
  • animation-delay: 指定动画开始前的延迟。
  • animation-iteration-count: 指定动画播放的次数,可以是数字(如 2),或者 infinite(无限循环)。
  • animation-direction: 指定动画的播放方向。
    • normal: 默认,正常播放。
    • reverse: 反向播放。
    • alternate: 轮换播放(第1次正常,第2次反向...)。
    • alternate-reverse: 轮换反向播放(第1次反向,第2次正常...)。
  • animation-fill-mode: 指定动画结束后的状态。
    • none: 默认,动画结束后回到原始状态。
    • forwards: 动画结束后,保持最后一帧的状态。
    • backwards: 动画开始前,保持第一帧的状态(在 delay 期间有效)。
    • both: 同时应用 forwardsbackwards

同样,也存在一个简写属性 animation

综合示例:一个弹跳的盒子

HTML:

<div class="box"></div>

CSS:

.box {
  width: 100px;
  height: 100px;
  background-color: #9b59b6;
  margin: 50px;
}
/* 1. 定义关键帧动画 */
@keyframes bounce {
  0%, 20%, 50%, 80%, 100% {
    transform: translateY(0);
  }
  40% {
    transform: translateY(-30px);
  }
  60% {
    transform: translateY(-15px);
  }
}
/* 2. 将动画应用到元素上 */
.box {
  animation-name: bounce;
  animation-duration: 1.5s;
  animation-timing-function: ease;
  animation-iteration-count: infinite;
  /* 使用简写属性 */
  animation: bounce 1.5s ease infinite;
}

代码解析:

  1. 我们定义了一个名为 bounce 的动画,在 0%, 20%, 50%, 80%, 100% 这些时间点,盒子都在原始位置(translateY(0)),在 40% 时,它向上移动 -30px,在 60% 时,它向上移动 -15px,这样就形成了弹跳的效果。
  2. 我们使用 animation 简写属性,将 bounce 动画应用到 .box 元素上,让它持续 5s,以 ease 的节奏,无限循环 (infinite) 播放。

第三部分:进阶技巧与最佳实践

transformopacity 的性能优势

在进行动画时,尽量优先使用 transform (如 translate, scale, rotate) 和 opacity 属性。

为什么? 现代浏览器对这两个属性有专门的优化,它们不会触发页面的重排,只会触发重绘,性能开销远小于改变 width, height, margin, left 等会触发重排的属性。

性能优化前 (不推荐):

.box {
  width: 100px;
  animation: grow 1s ease infinite;
}
@keyframes grow {
  100% { width: 200px; }
}

性能优化后 (推荐):

.box {
  width: 100px;
  animation: grow 1s ease infinite;
}
@keyframes grow {
  100% { transform: scale(2); }
}

动画触发

默认情况下,CSS 动画在页面加载后就会自动开始,如果想在某个特定事件(如点击、悬停)后触发动画,可以结合 hover 或 JavaScript 来控制。

示例:点击后触发动画

HTML:

<div class="click-box"></div>

CSS:

.click-box {
  width: 100px;
  height: 100px;
  background-color: #1abc9c;
  /* 初始状态,动画未播放 */
  animation: none; /* 或者直接不写 animation */
}
.click-box.animate {
  animation: spin 1s ease;
}
@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

JavaScript:

document.querySelector('.click-box').addEventListener('click', function() {
  this.classList.add('animate');
  // 如果想每次点击都重新播放,需要先移除再添加
  // this.addEventListener('animationend', function() {
  //   this.classList.remove('animate');
  // });
});

动画事件

你可以使用 JavaScript 监听动画的关键事件,从而执行更复杂的逻辑。

  • animationstart: 动画开始时触发。
  • animationend: 动画结束时触发。
  • animationiteration: 每次动画循环一次时触发(仅对 iteration-count > 1 有效)。
const box = document.querySelector('.click-box');
box.addEventListener('animationstart', () => {
  console.log('动画开始了!');
});
box.addEventListener('animationend', () => {
  console.log('动画结束了!');
});
box.addEventListener('animationiteration', () => {
  console.log('动画完成了一次循环!');
});

第四部分:总结与对比

特性 CSS transition CSS @keyframes animation
控制能力 简单,只能在两个状态间过渡 强大,可以定义多个关键帧
触发方式 通常由用户交互(如 hover)或脚本改变样式触发 页面加载后自动开始,或通过脚本类名触发
关键帧 有 (@keyframes)
循环次数 需要通过 JavaScript 循环类名来实现 内置 iteration-count 属性(infinite
方向控制 内置 direction 属性
结束状态 返回原始状态 可通过 fill-mode 控制保持结束状态
适用场景 简单的悬停效果、按钮反馈、淡入淡出 复杂的序列动画、加载动画、Logo动效

学习资源推荐

  • MDN Web Docs: CSS TransitionsCSS Animations 是最权威、最详细的参考资料。
  • CSS-Tricks: 有大量关于 CSS 动画的实用文章和技巧。
  • CodePen / JSFiddle: 在线代码编辑器,你可以看到无数优秀的动画实例,并直接修改代码进行学习。

希望这份教程能帮助你系统地掌握 CSS3 动画!动手实践是学习的最好方式,快去创建属于你自己的酷炫动画吧!