css-animation

CSS 动画的常见属性、使用方式,以及和过渡效果的选择边界。

#status / growing #type / concept #resource / css

[!info] related notes

css-animation

CSS 动画的核心是:让样式在一段时间内从一个状态变化到另一个状态。

一句话定义

如果只是“某个状态切到另一个状态”,优先想 transition;如果要定义更完整的关键帧过程,使用 animation

先抓住两条主路

CSS 里“让东西动起来”最常见的是两类:

  • transition
  • animation

但它们更像“播放机制”,真正变化的通常是具体属性,比如 transformopacitycolorbackground-color

所以更准确地说:

  • transition / animation 决定怎么播放
  • transform / opacity 决定到底变什么

transitionanimation 到底差在哪

transition

适合“从一个状态平滑过渡到另一个状态”。

典型场景:

  • hover
  • focus
  • active
  • class 切换
  • 折叠展开

它依赖的是“状态变化”。如果没有前后两个状态,就不会自己播放。

animation

适合“主动播放一段预先定义好的动画过程”。

典型场景:

  • 元素入场
  • loading
  • 无限循环旋转
  • 呼吸灯
  • 多关键帧节奏变化

它依赖的是 @keyframes,可以直接定义 0%、50%、100% 等多个阶段。

常用属性

属性说明示例值
animation-name指定要运用的关键帧名称slideIn
animation-duration动画完成一个周期所需时间1s1000ms
animation-timing-function动画的速度曲线linear, ease, ease-in, ease-out, cubic-bezier(0.1, 0.7, 1.0, 0.1)
animation-delay动画开始前的延迟时间2s
animation-iteration-count动画播放次数3, infinite
animation-direction动画是否反向播放normal, reverse, alternate, alternate-reverse
animation-fill-mode动画执行前后如何应用样式none, forwards, backwards, both
animation-play-state动画运行或暂停running, paused

最常见的题:hover 时变色 + 变圆 + 200ms

题目一般像这样:

  • 一个 100 x 100 的红色 div
  • 鼠标移上去后变黑
  • 同时变成圆形
  • 动画时间 200ms

这类题其实更适合直接用 transition

<div class="box"></div>
.box {
  width: 100px;
  height: 100px;
  background: red;
  border-radius: 0;
  transition: background-color 200ms ease, border-radius 200ms ease;
}

.box:hover {
  background: black;
  border-radius: 50%;
}

为什么这里更推荐 transition

  • 因为只有“初始态 -> hover 态”两个状态
  • 不需要多段关键帧
  • 写法更短,也更符合题目意图

什么时候该用 animation

当题目要求:

  • 自动播放
  • 无限循环
  • 多阶段变化
  • 精确控制 0%、50%、100% 等过程

这时再写 @keyframes

@keyframes pulse {
  0% {
    transform: scale(1);
  }

  50% {
    transform: scale(1.1);
  }

  100% {
    transform: scale(1);
  }
}

.box {
  animation: pulse 1s infinite;
}

一个更直观的对比

transition 更像补间

你只告诉浏览器:

从 A 状态变到 B 状态时,用一段时间平滑过去。

.card {
  transition: transform 0.25s ease, opacity 0.25s ease;
}

.card:hover {
  transform: translateY(-4px);
  opacity: 0.92;
}

animation 更像时间轴剧本

你直接告诉浏览器:

第 0% 是什么样,第 50% 是什么样,第 100% 是什么样。

@keyframes bounce {
  0% {
    transform: translateY(0);
  }

  30% {
    transform: translateY(-20px);
  }

  60% {
    transform: translateY(0);
  }

  100% {
    transform: translateY(-8px);
  }
}

.ball {
  animation: bounce 0.8s ease;
}

开发里怎么选

可以先问自己两个问题:

1. 这个效果是不是“状态切换触发”的

如果是,优先想 transition

例如:

  • hover 反馈
  • 输入框聚焦
  • 展开收起
  • 通过 class 切换显隐

2. 这个效果是不是“自己播放的一段过程”

如果是,优先想 animation

例如:

  • 页面入场
  • loading 旋转
  • 循环闪烁
  • 多阶段弹跳

transform 为什么在动画里这么常见

很多人会误以为 transform 本身就是动画类型,其实不是。

  • transform 是被变化的属性
  • transition / animation 是让变化有时间过程的机制

最常做动画的 transform 包括:

  • translate
  • scale
  • rotate

例如:

.box {
  transition: transform 0.3s ease;
}

.box:hover {
  transform: scale(1.05);
}
@keyframes spin {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

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

显示隐藏为什么常配合 opacity

不是所有属性都适合做平滑动画。

  • opacitytransform 这类属性通常可以自然插值
  • display 这类属性不是连续值,通常不能平滑过渡

所以做淡入淡出时,更常见的写法不是直接动画 display,而是:

.modal {
  opacity: 0;
  transform: scale(0.95);
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.modal.show {
  opacity: 1;
  transform: scale(1);
}

这也是为什么“显示隐藏”经常要联动 display-none-visibility-hidden-opacity-zero 一起理解。

timing function 在控制什么

不管是 transition 还是 animationtiming-function 控制的都是速度曲线,不是总时长。

常见直觉:

  • linear:匀速
  • ease:默认,更柔和
  • ease-in:前慢后快
  • ease-out:前快后慢
  • ease-in-out:两头慢,中间快

经验上:

  • loading 旋转常用 linear
  • hover 反馈常用 easeease-out

两者能不能一起用

可以,而且很常见。

例如元素入场用 animation,hover 反馈再用 transition

@keyframes fadeSlideIn {
  from {
    opacity: 0;
    transform: translateY(20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.card {
  animation: fadeSlideIn 0.6s ease forwards;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover {
  transform: translateY(-4px);
}

性能上的保守规则

CSS 动画不等于一定高性能。

优先考虑这些属性:

  • transform
  • opacity

更要谨慎这些属性:

  • width
  • height
  • top
  • left
  • margin

因为它们更容易引发布局和重绘。要理解原因,可以回看 reflow-vs-repaint-interview-questionbrowser-rendering-process

一句话记忆法

  • transition:状态变了,我帮你慢慢过渡
  • animation:我自己定义一整段时间轴来播放

面试里一句话怎么答

如果只是 hover 切换颜色和圆角,我会优先用 transition;如果是多阶段、循环或更复杂的时间轴动画,我才会用 animation + keyframes

创建于 2026/3/6 更新于 2026/5/27