🎬 CSS 动画总览

理解 CSS 动画的两种实现方式

CSS 动画的两种实现方式

CSS 提供了两种创建动画的方式:Transition(过渡)Animation(动画)。 它们都可以让 CSS 属性的变化变得平滑,但适用场景不同。

重要:Transition 和 Animation 都可以动画任何 CSS 属性(transform、opacity、color、width 等), 不是只能用于 transform。Transform 只是一个常用的动画属性。

⚠️ 核心理解:CSS 属性的变化默认是瞬间的

任何 CSS 属性的变化,默认都是瞬间完成的,没有动画过程。 这包括 transform、width、opacity、color、background 等所有属性。

/* ❌ 单独改变属性 - 瞬间变化,无动画 */

/* transform 单独使用 */
.box {
  transform: rotate(0deg);
}
.box:hover {
  transform: rotate(45deg); /* 立即旋转,无动画 */
}

/* width 单独使用 */
.box {
  width: 100px;
}
.box:hover {
  width: 200px; /* 立即变宽,无动画 */
}

/* opacity 单独使用 */
.box {
  opacity: 1;
}
.box:hover {
  opacity: 0.5; /* 立即变透明,无动画 */
}

/* background 单独使用 */
.box {
  background: red;
}
.box:hover {
  background: blue; /* 立即变色,无动画 */
}

如果想要平滑的动画效果,必须配合 Transition 或 Animation 使用。

/* ✅ 配合 transition - 平滑过渡 */
.box {
  width: 100px;
  opacity: 1;
  background: red;
  transition: all 0.3s ease; /* 添加过渡效果 */
}
.box:hover {
  width: 200px; /* 0.3 秒内平滑变宽 */
  opacity: 0.5; /* 0.3 秒内平滑变透明 */
  background: blue; /* 0.3 秒内平滑变色 */
}

⚡ Transition(过渡)- 简单的状态变化

作用:让 CSS 属性的变化变得平滑,需要触发条件(如 :hover、:focus、JavaScript 改变类名)。

特点:只有开始和结束两个状态,简单易用,适合交互效果。

完整写法

/* 所有属性分开写 */
.box {
  transition-property: transform; /* 要过渡的属性 */
  transition-duration: 0.3s; /* 持续时间 */
  transition-timing-function: ease; /* 缓动函数 */
  transition-delay: 0s; /* 延迟时间 */
}

简写语法

/* 语法:transition: property duration timing-function delay; */

/* 完整简写 */
.box {
  transition: transform 0.3s ease 0s; /* 属性 时长 缓动 延迟 */
}

/* 常用简写(省略延迟,默认 0s)*/
.box {
  transition: transform 0.3s ease;
}

/* 最简写法(省略缓动,默认 ease)*/
.box {
  transition: transform 0.3s;
}

/* 过渡所有属性 */
.box {
  transition: all 0.3s ease; /* ↑ 所有可动画的属性都会过渡 */
}

多个属性分别设置

/* 不同属性使用不同的过渡效果 */
.box {
  transition: transform 0.3s ease,
                opacity 0.5s linear,
                background 0.2s ease-in;
}

实际应用示例

/* 按钮悬停效果 */
.button {
  transform: translateY(0);
  transition: transform 0.2s ease;
}

.button:hover {
  transform: translateY(-3px);
}

/* 卡片悬停效果 */
.card {
  transition: all 0.3s ease;
}

.card:hover {
  transform: translateY(-5px);
  box-shadow: 0 10px 20px rgba(0,0,0,0.1);
}

可以过渡的属性:transform、opacity、color、background、width、height、margin、padding 等大部分 CSS 属性。

🎬 Animation(动画)- 复杂的关键帧动画

作用:创建复杂的、可重复的动画效果,必须配合 @keyframes 使用。

特点:可以有多个中间状态,可以自动播放、循环播放,更强大灵活。

第一步:定义关键帧

/* 使用 from/to */
@keyframes slideIn {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(0);
  }
}

/* 使用百分比(更灵活)*/
@keyframes bounce {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-30px);
  }
  100% {
    transform: translateY(0);
  }
}

第二步:完整写法

/* 所有属性分开写 */
.box {
  animation-name: slideIn; /* 动画名称(@keyframes 定义的)*/
  animation-duration: 1s; /* 持续时间 */
  animation-timing-function: ease; /* 缓动函数 */
  animation-delay: 0s; /* 延迟时间 */
  animation-iteration-count: 1; /* 播放次数(1 或 infinite)*/
  animation-direction: normal; /* 播放方向 */
  animation-fill-mode: none; /* 填充模式 */
  animation-play-state: running; /* 播放状态 */
}

简写语法

/* 语法:animation: name duration timing-function delay iteration-count direction fill-mode; */

/* 完整简写 */
.box {
  animation: slideIn 1s ease 0s 1 normal none;
  /* 名称 时长 缓动 延迟 次数 方向 填充 */
}

/* 常用简写(省略延迟、方向、填充)*/
.box {
  animation: slideIn 1s ease;
}

/* 最简写法(省略缓动,默认 ease)*/
.box {
  animation: slideIn 1s;
}

常用场景

/* 无限循环 */
.spinner {
  animation: spin 2s linear infinite; /* ↑ 无限循环 */
}

/* 保持最后一帧 */
.fade-in {
  animation: fadeIn 1s ease forwards; /* ↑ 结束后保持最后状态 */
}

/* 延迟 + 保持 */
.slide-in {
  animation: slideIn 0.5s ease 0.3s 1 normal forwards;
  /* ↑延迟0.3秒 ↑保持最后状态 */
}

/* 来回播放 */
.pulse {
  animation: pulse 1s ease-in-out infinite alternate; /* ↑ 来回交替 */
}

实际应用示例

/* 加载动画 */
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.loader {
  animation: spin 1s linear infinite;
}

/* 页面加载淡入 */
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.page {
  animation: fadeIn 0.5s ease;
}

📊 Transition vs Animation 对比

特性 Transition(过渡) Animation(动画)
定义方式 直接在元素上 需要 @keyframes
触发方式 需要状态变化(:hover、JS 等) 自动播放
状态数量 2 个(开始 → 结束) 多个(0%, 25%, 50%, 100%...)
循环播放 ❌ 不支持 ✅ 支持(infinite)
可用属性 任何可动画的 CSS 属性 任何可动画的 CSS 属性
复杂度 简单 复杂
使用场景 悬停效果、简单交互 加载动画、复杂动画

🎯 Transform 的角色

Transform 是一个 CSS 属性,不是动画方式!它可以单独使用,也可以配合 Transition 或 Animation 使用。

三种使用方式对比

❌ 单独使用

有效果,但瞬间变化,无动画过程

✅ 配合 Transition

平滑过渡,需要触发条件

✅ 配合 Animation

复杂动画,可自动播放

代码对比

/* 方式 1:单独使用 transform - 瞬间变化 ❌ */
.box1 {
  transform: rotate(45deg); /* 页面加载时立即旋转 45 度,无动画 */
}

.box1:hover {
  transform: rotate(90deg); /* 悬停时立即旋转到 90 度,无动画 */
}

/* 方式 2:transform + transition - 平滑过渡 ✅ */
.box2 {
  transform: rotate(0deg);
  transition: transform 0.5s ease; /* 添加过渡效果 */
}

.box2:hover {
  transform: rotate(45deg); /* 悬停时在 0.5 秒内平滑旋转到 45 度 */
}

/* 方式 3:transform + animation - 持续动画 ✅ */
@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.box3 {
  animation: spin 2s linear infinite; /* 持续旋转,每圈 2 秒 */
}

📝 总结

  • Transform 单独使用 = 有效果,但瞬间完成(没有动画过程)
  • Transform + Transition = 有平滑的过渡动画
  • Transform + Animation = 有复杂的关键帧动画

📐 是否影响文档流?

重要概念:Transition 和 Animation 本身不是变换,它们只是让属性变化变得平滑。 是否影响文档流,取决于你动画的是什么属性。

Transform - 永远不影响文档流 ✅

/* Transform 只是视觉变化,不影响布局 */
.box {
  transform: translate(100px, 100px);
  /* 元素视觉上移动了,但原来的空间仍然占据 */
  /* 不会影响其他元素的布局 */
}

属性分类对比

属性类型 是否影响文档流 示例 性能
Transform ❌ 不影响 translate, rotate, scale, skew ⚡ 最佳(仅合成)
Opacity ❌ 不影响 opacity ⚡ 最佳(仅合成)
Filter ❌ 不影响 blur, brightness, contrast ⚡ 最佳(仅合成)
盒模型 ✅ 影响 width, height, margin, padding ⚠️ 差(触发重排)
定位 ✅ 影响 top, left, right, bottom ⚠️ 差(触发重排)
颜色 ❌ 不影响 color, background-color, border-color ⚡ 好(仅重绘)

代码示例对比

/* ✅ 不影响文档流 - 动画 transform */
.box {
  transition: transform 0.3s;
}
.box:hover {
  transform: translateX(100px); /* 只是视觉变化 */
}

/* ✅ 不影响文档流 - 动画 opacity */
.box {
  transition: opacity 0.3s;
}
.box:hover {
  opacity: 0.5; /* 只是透明度变化 */
}

/* ❌ 影响文档流 - 动画 width */
.box {
  transition: width 0.3s;
}
.box:hover {
  width: 200px; /* 会影响其他元素的位置! */
}

/* ❌ 影响文档流 - 动画 margin */
.box {
  transition: margin 0.3s;
}
.box:hover {
  margin-left: 50px; /* 会影响其他元素的位置! */
}

⚡ 性能最佳实践

为了性能和避免布局抖动,推荐只动画这些属性:

  • transform - 平移、旋转、缩放、倾斜
  • opacity - 透明度
  • filter - 滤镜效果

这些属性只触发合成(Composite),不会触发重排(Reflow)重绘(Repaint),性能最好。

/* ✅ 推荐:高性能动画 */
.box {
  transition: transform 0.3s, opacity 0.3s;
}

/* ❌ 避免:会触发重排,性能差 */
.box {
  transition: width 0.3s, height 0.3s, margin 0.3s;
}

💡 如何选择?

  • 使用 Transition:当你需要简单的状态变化,如按钮悬停、卡片展开等
  • 使用 Animation:当你需要复杂的动画,如加载动画、页面进入动画、循环动画等
  • 单独使用 Transform:当你只需要静态的变换效果,不需要动画过程

记住:

  • Transition 和 Animation 都可以动画任何 CSS 属性,不只是 transform
  • Transform 可以单独使用,但没有动画过程,是瞬间变化的
  • 如果想要平滑的动画效果,需要配合 Transition 或 Animation
  • Transform 永远不影响文档流,是否影响文档流取决于动画的属性
  • 推荐只动画 transform、opacity、filter,性能最好