@keyframes - 关键帧动画

创建复杂的、可重复的动画效果

什么是 @keyframes?

@keyframes 用于定义动画的关键帧,可以创建比 transition 更复杂的动画效果。它允许你精确控制动画在不同时间点的状态。

  • 关键帧:定义动画在特定时间点的样式
  • 可重复:动画可以循环播放
  • 更灵活:可以定义多个中间状态
  • 自动播放:页面加载时自动开始

基本语法

/* 方式 1:使用 from 和 to */
@keyframes animationName {
  from { transform: translateX(0); }
  to { transform: translateX(100px); }
}

/* 方式 2:使用百分比 */
@keyframes animationName {
  0% { transform: translateX(0); }
  50% { transform: translateX(100px); }
  100% { transform: translateX(0); }
}

/* 应用动画 */
.element {
  animation: animationName 2s ease-in-out infinite;
}

from/to vs 百分比

使用 from 和 to

  • from - 等同于 0%,表示动画的起始状态
  • to - 等同于 100%,表示动画的结束状态
  • 适用场景:简单的两个状态之间的过渡
  • 优点:语义清晰,代码简洁
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

使用百分比

  • 0% - 动画开始时的状态
  • 50% - 动画进行到一半时的状态
  • 100% - 动画结束时的状态
  • 适用场景:需要多个中间状态的复杂动画
  • 优点:可以精确控制动画的每个阶段
@keyframes complexMove {
  0% { transform: translateX(0); }
  25% { transform: translateX(100px); }
  50% { transform: translateX(100px) translateY(50px); }
  75% { transform: translateX(0) translateY(50px); }
  100% { transform: translateX(0) translateY(0); }
}

选择建议:如果只有开始和结束两个状态,使用 from/to 更简洁;如果需要多个中间状态,使用百分比更灵活

示例对比:from/to vs 百分比

下面两个动画效果完全相同,只是写法不同

使用 from/to

@keyframes simple {
  from { opacity: 0; }
  to { opacity: 1; }
}

使用百分比

@keyframes simple {
  0% { opacity: 0; }
  100% { opacity: 1; }
}

等价关系:from = 0%,to = 100%。两种写法完全等价,选择你喜欢的即可

示例 1:滑入动画(使用 from/to)

元素从左侧滑入并淡入

滑入
@keyframes slideIn {
  from {
    transform: translateX(-100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

.box {
  animation: slideIn 1s ease-out;
}

示例 2:弹跳动画

元素持续上下弹跳

弹跳
@keyframes bounce {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-30px);
  }
}

.box {
  animation: bounce 1s ease-in-out infinite;
  /* infinite 表示无限循环 */
}

示例 3:颜色变化

背景色在多个颜色之间循环变化

颜色
@keyframes colorChange {
  0% { background: #10b981; }
  33% { background: #3b82f6; }
  66% { background: #8b5cf6; }
  100% { background: #10b981; }
}

.box {
  animation: colorChange 3s ease-in-out infinite;
}

示例 4:3D 旋转

元素在 3D 空间中持续旋转

3D
@keyframes rotate3d {
  from {
    transform: rotate3d(0, 1, 0, 0deg);
  }
  to {
    transform: rotate3d(0, 1, 0, 360deg);
  }
}

.box {
  animation: rotate3d 3s linear infinite;
}

animation 属性详解

.element {
  animation: name duration timing-function delay iteration-count direction fill-mode;
}
  • animation-name - 动画名称(@keyframes 定义的名称)
  • animation-duration - 持续时间(如 2s, 500ms)决定动画何时结束
  • animation-timing-function - 缓动函数(ease, linear, ease-in-out 等)
  • animation-delay - 延迟时间(如 1s)
  • animation-iteration-count - 播放次数(数字或 infinite)
  • animation-direction - 播放方向(见下方详解)
  • animation-fill-mode - 填充模式(见下方详解)

重要:动画从 0% 到 100% 的时间由 animation-duration 决定。例如 duration: 2s 表示动画会在 2 秒内完成从 0% 到 100% 的所有关键帧

animation-direction 详解

控制动画的播放方向

normal(默认)

正常播放:0% → 100%

reverse

反向播放:100% → 0%

alternate

交替播放:正向 → 反向 → 正向...

alternate-reverse

反向交替:反向 → 正向 → 反向...

.normal {
  animation-direction: normal;
}
.reverse {
  animation-direction: reverse;
}
.alternate {
  animation-direction: alternate;
}
.alternate-reverse {
  animation-direction: alternate-reverse;
}

animation-fill-mode 简介

控制动画开始前和结束后元素的状态

  • none - 默认值,延迟期间和结束后都不应用动画样式
  • forwards - 动画结束后保持最后一帧的状态(最常用!)
  • backwards - 延迟期间应用第一帧样式
  • both - 结合 backwards 和 forwards 的效果

🎯 想深入理解 fill-mode?

👉 点击查看 animation-fill-mode 详细演示页面
包含更直观的对比演示、完整代码示例和最佳实践建议

/* 基本用法 */
.element {
  animation-fill-mode: forwards; /* 保持最后一帧 */
}

/* 简写形式 */
.element {
  animation: myAnimation 2s ease-out forwards;
}

常见应用场景