CSS 动画两大类:transition 与 animation

CSS 做动画有两套工具:transition(过渡)和 animation + keyframes(关键帧动画)。transition 是简单场景——状态从 A 变到 B,中间平滑过渡;animation 是复杂场景——多帧循环、入场、精细控制的长动画。

打个比方:transition 像是开门——你指定门从关到开怎么过渡,浏览器自动算中间帧;animation 像是拍动画——你一帧一帧定义每个时间点门在什么位置,浏览器按你的脚本播放。

能用 transition 解决的不要用 animation。transition 声明更少、性能更好,覆盖了悬停变色、位置移动、大小缩放 80% 的交互动效。
本文核心知识点
  • transition属性变化的平滑过渡,一行代码搞定悬停动效。
  • @keyframes定义多帧动画脚本,配合 animation 属性播放。
  • cubic-bezier自定义缓动曲线,决定动画的"手感"。
  • transform/opacity唯一走 GPU 加速的两个属性,动画必用。
CSS 动画示意:深蓝渐变背景上多条弧形运动轨迹,沿轨迹排列菱形关键帧标记,左下角小球沿虚线弹出
动画就是轨迹:关键帧标记了每个时间点的位置,浏览器把它们连成平滑的曲线。

transition:状态变化的平滑过渡

transition 最常见的用途是悬停效果。默认情况下,鼠标移到按钮上,颜色瞬间变化——加上 transition 后,颜色在 0.2 秒内平滑过渡,手感立刻精致起来。

.btn {
  background: #1E5FA8;
  transition: background 0.2s ease, transform 0.2s ease;
}
.btn:hover {
  background: #164A85;
  transform: translateY(-2px);
}

transition 的四个参数:要过渡的属性、时长、缓动函数、延迟。可以同时过渡多个属性,用逗号分隔。transition: all 0.2s ease 是简写,但性能不如只指定需要过渡的属性。

属性作用常用值
transition-property哪些属性参与过渡background, transform, opacity
transition-duration过渡时长0.2s, 0.3s
transition-timing-function缓动曲线ease, linear, ease-in-out
transition-delay延迟多久开始0s, 0.1s

transition 是单向的:鼠标移开时它也会反向过渡回去——不需要你写 hover 以外的代码。这就是它比 animation 简单的地方。

keyframes:多帧复杂动画

当动画需要多帧、循环、或者自动播放(不需要用户触发),就要用 @keyframes。它定义一个动画脚本,从 0% 到 100% 分阶段描述每个时间点的状态。

@keyframes bounce {
  0%   { transform: translateY(0); }
  50%  { transform: translateY(-20px); }
  100% { transform: translateY(0); }
}

.loading-ball {
  animation: bounce 1s ease infinite;
}

这段代码让小球在垂直方向上下弹跳,1 秒一个周期,无限循环。animation 属性把动画名、时长、缓动、循环次数串起来。

animation 的常用参数和 transition 类似,但多了两个:animation-iteration-count(infinite 表示无限循环)和 animation-direction(alternate 表示来回播放)。

@keyframes fadeSlideIn {
  from {
    opacity: 0;
    transform: translateX(-20px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

.card {
  animation: fadeSlideIn 0.4s ease forwards;
}

forwards 表示动画结束后保持最终状态。入场动画最常用这个——页面加载时卡片从左侧淡入滑入,停在最终位置。

cubic-bezier:缓动函数决定手感

同样一段动画,缓动曲线不同,手感天差地别。ease 是默认值——开始快、结束慢;linear 匀速——像钟表指针;ease-in-out 两头慢中间快。

想要更精致的手感,用 cubic-bezier() 自定义贝塞尔曲线。四个参数是两个控制点的坐标:

/* 常见的精致缓动 */
transition: transform 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);

/* 回弹效果(略微超出目标再回来) */
transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);

第二条曲线的 y 值超过了 1,动画会略微超出目标位置再弹回来——这就是"回弹"手感。做按钮点击、卡片悬停时用这种曲线,动效会显得很有弹性。

有一个在线工具叫 cubic-bezier.com,可以拖动点直观调曲线,调好后复制 CSS 代码。做动效时强烈建议用这种工具,不要凭感觉写数字。

transform 与 opacity:性能最优属性

不是所有 CSS 属性都适合做动画。改 width、height、left、top 会触发浏览器重新布局(reflow),每帧都要重算整个页面的排版——非常卡。改 color、background 会触发重绘(repaint)——也不便宜。

只有 transform 和 opacity 两个属性走 GPU 加速:它们在合成层处理,不触发重排和重绘,帧率稳定 60fps。

要做的动效错误写法正确写法
移动元素left: 100pxtransform: translateX(100px)
缩放元素width: 120%transform: scale(1.2)
淡入淡出color: rgba(0,0,0,0.5)opacity: 0.5
旋转元素—transform: rotate(45deg)

记住一个原则:动画只动 transform 和 opacity。位置用 translate、大小用 scale、旋转用 rotate、透明度用 opacity——全部走 GPU,丝滑流畅。