首页 / CSS 入门教程 / 动画 animation

CSS 入门教程

动画 animation

本教程共 44 篇 · 第 39 篇 · 更新于 2026-07-29 · 约 13 分钟阅读

动画animationkeyframes关键帧循环动画

39. 动画 animation

本节目标:掌握 @keyframes 关键帧动画,理解 animation 系列属性的作用,能够创建自动播放、循环、往返的复杂动画效果。

过渡需要状态变化触发,动画不需要。定义好运价规则,元素就能自动执行动画,甚至可以无限循环。

@keyframes:定义关键帧

动画的核心是 @keyframes 规则,它定义了动画过程中各阶段的样式。

@keyframes 动画名称 {
  from { 起始样式 }
  to   { 结束样式 }
}

或者用百分比:

@keyframes 动画名称 {
  0%   { 起始样式 }
  50%  { 中间样式 }
  100% { 结束样式 }
}
<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    @keyframes color-change {
      from { background: #E74C3C; }
      to   { background: #3498DB; }
    }
    .box {
      width: 100px;
      height: 100px;
      background: #E74C3C;
      animation: color-change 2s;
    }
  </style>
</head>
<body>
  <div class="box"></div>
</body>
</html>

animation-name 与 animation-duration

动画定义好后,需要绑定到元素上。animation-name 指定用哪个动画,animation-duration 指定持续时间。

.box {
  animation-name: slide;
  animation-duration: 3s;
}

如果只写

不写 duration,动画不会播放,因为默认时长是 0。

animation-iteration-count:播放次数

控制动画播放几次。

animation-iteration-count: 3;       /* 播放 3 次 */
animation-iteration-count: infinite; /* 无限循环 */
<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    @keyframes pulse {
      0%, 100% { transform: scale(1); }
      50%      { transform: scale(1.15); }
    }
    .dot {
      width: 40px;
      height: 40px;
      background: #E74C3C;
      border-radius: 50%;
      animation: pulse 1s ease-in-out infinite;
      margin: 40px;
    }
  </style>
</head>
<body>
  <div class="dot"></div>
</body>
</html>

animation-direction:播放方向

控制动画的播放方向。

效果
normal正向播放(默认)
reverse反向播放
alternate正向-反向-正向交替
alternate-reverse反向-正向-反向交替
<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    @keyframes bounce {
      0%   { transform: translateY(0); }
      100% { transform: translateY(-30px); }
    }
    .ball {
      width: 50px;
      height: 50px;
      background: #3498DB;
      border-radius: 50%;
      animation: bounce 0.5s ease-in-out infinite alternate;
      margin: 50px;
    }
  </style>
</head>
<body>
  <div class="ball"></div>
</body>
</html>
Tip

是做往返动画的最佳选择。配合 infinite,一个关键帧就能做出平滑的来回效果。

animation-delay:延迟播放

动画开始前的等待时间。负值会让动画从中间开始播放。

animation-delay: 2s;   /* 延迟 2 秒 */
animation-delay: -1s;  /* 已经播放了 1 秒的状态开始 */

animation-fill-mode:填充模式

控制动画在播放前后,元素应用什么样式。

效果
none播放前后不应用任何关键帧样式
forwards保留最后一帧的样式
backwards应用第一帧的样式(延迟期间也有效)
both同时遵循 forwards 和 backwards
<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    @keyframes fade-in {
      from { opacity: 0; transform: translateY(20px); }
      to   { opacity: 1; transform: translateY(0); }
    }
    .card {
      width: 200px;
      padding: 20px;
      background: #2ECC71;
      color: white;
      border-radius: 8px;
      opacity: 0; /* 初始不可见 */
      animation: fade-in 0.6s ease-out 1s both;
      /* both: 延迟期间用 from 样式(opacity:0),结束后保留 to 样式 */
    }
  </style>
</head>
<body>
  <div class="card">1 秒后淡入</div>
</body>
</html>

做入场动画时,

非常常用。既保证延迟期间元素不可见,又保证结束后保持最终状态。

animation-play-state:暂停与运行

控制动画的播放状态。常用于悬停时暂停。

.box {
  animation: spin 2s linear infinite;
}
.box:hover {
  animation-play-state: paused;
}
<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    @keyframes spin {
      from { transform: rotate(0deg); }
      to   { transform: rotate(360deg); }
    }
    .spinner {
      width: 60px;
      height: 60px;
      border: 4px solid #E0E0E0;
      border-top-color: #3498DB;
      border-radius: 50%;
      animation: spin 1s linear infinite;
      margin: 40px;
    }
  </style>
</head>
<body>
  <div class="spinner" title="悬停暂停"></div>
</body>
</html>

animation-timing-function:速度曲线

和过渡一样,控制动画过程中的速度变化。

animation-timing-function: ease;           /* 默认 */
animation-timing-function: steps(4);       /* 分 4 步完成 */
animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* 回弹 */
Tip

是做帧动画的关键。比如加载图标分成 8 帧,就用 steps(8)

animation 简写属性

animation 按顺序包含:name、duration、timing-function、delay、iteration-count、direction、fill-mode、play-state。

/* 完整写法 */
animation: slide 3s ease-in-out 1s 2 alternate forwards;

/* 最少需要 name 和 duration */
animation: slide 3s;
<!DOCTYPE html>
<html lang="zh">
<head>
  <style>
    @keyframes loading {
      0%   { width: 0; background: #E74C3C; }
      50%  { width: 50%; background: #F39C12; }
      100% { width: 100%; background: #2ECC71; }
    }
    .progress {
      height: 8px;
      background: #E74C3C;
      border-radius: 4px;
      animation: loading 3s ease-in-out forwards;
      margin: 40px auto;
      max-width: 400px;
    }
  </style>
</head>
<body>
  <div class="progress"></div>
</body>
</html>

多个动画

一个元素可以同时应用多个动画,用逗号分隔:

.box {
  animation: fade-in 1s ease-out, scale-up 0.5s ease-out 0.5s;
}

过渡 vs 动画

对比过渡动画
触发方式需要状态变化自动播放
关键帧只有开始和结束可以有多个
循环不能可以无限循环
适用场景悬停、开关反馈加载动画、持续动效

实际项目中,简单的状态变化用过渡,复杂的、需要循环的动效用动画。两者经常结合使用。

动画属性速查

属性作用默认值
animation-name动画名称none
animation-duration动画时长0s
animation-timing-function速度曲线ease
animation-delay延迟时间0s
animation-iteration-count播放次数1
animation-direction播放方向normal
animation-fill-mode填充模式none
animation-play-state播放状态running
animation简写