技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTCSS

CSS 动画:animation、transition、transform、translate 傻傻分不清

所属馆藏
CSS
文件格式
Markdown
原始路径
CSS/06-CSS动画:animation、transition、transform、translate傻傻分不
本文目录9 个章节
  1. 一、transition:过渡
  2. 二、animation:关键帧动画
  3. 三、transform:变换
  4. 四、translate:平移
  5. 五、transition、animation、transform、translate 对比
  6. 六、CSS 动画与 JavaScript 动画
  7. 七、无障碍与性能注意事项
  8. 总结
  9. 参考资料

CSS 动画:animationtransitiontransformtranslate 傻傻分不清

Category(分类): CSS Status: 已整理

CSS 属性很多,有些属性无论是拼写还是字面意思都容易混淆。animationtransitiontransformtranslate 经常同时出现在动画代码中,但它们解决的问题并不相同。

属性含义
animation根据 @keyframes 定义的关键帧和时间轴运行动画,支持循环、反向、暂停和延迟等能力
transition在属性的计算值发生变化时,让元素从起始值平滑过渡到结束值
transform对元素进行平移、旋转、缩放、倾斜等几何变换;它本身不是动画,但可以被 transitionanimation 动画化
translate()transform 中的平移变换函数,例如 transform: translate(20px, 10px)
translate现代 CSS 中独立的变换属性,例如 translate: 20px 10px,不能简单理解为 transform 的属性值

先记住一句话:

transitionanimation 负责描述“如何随时间变化”;transformtranslate 负责描述“变化成什么样子”。

一、transition:过渡

1. 什么叫过渡?

过渡表示元素从某个计算值平滑地变化到另一个计算值。例如颜色从红色变为绿色:

.box {
  color: red;
  transition: color 0.3s ease;
}

.box:hover {
  color: green;
}

transition 不会凭空播放动画,它需要属性的计算值发生变化。常见的变化来源包括:

  • :hover:focus:checked 等伪类;
  • 类名变化;
  • JavaScript 修改内联样式或 CSS 类;
  • 媒体查询条件变化;
  • CSS 自定义属性变化;
  • DOM 状态变化。

下面是一个简单示例:

<div id="box"></div>
#box {
  width: 100px;
  height: 100px;
  background: green;
  transition: transform 1s ease-in 1s;
}

#box:hover {
  transform: rotate(180deg) scale(0.5);
}

鼠标移入时,transform 从初始值变化为旋转并缩小后的值,触发过渡;鼠标移出时,transform 又变化回初始值,因此会再次执行过渡。

transition 过渡效果

这里的 1s ease-in 1s 依次表示:

  • 过渡持续时间:1s
  • 时间函数:ease-in
  • 延迟时间:1s

2. transition 的特点

transition 的特点是依赖属性值的变化:

  1. 仅声明 transition 不会自动播放,必须先后存在可以比较的起始值和结束值;
  2. 每次计算值再次发生变化时,都可以重复执行,并不是真正的“一次性动画”;
  3. 它通常只描述起始状态和结束状态,不能像 @keyframes 那样显式定义多个时间节点;
  4. 可以同时过渡多个属性,但每一条过渡记录仍然描述一个属性或属性集合;
  5. 页面首次加载时通常不会因为初始样式的应用而自动播放,需要在加载后改变状态才会触发。

例如,同时过渡多个属性:

.box {
  color: #333;
  background-color: #fff;
  transform: translateX(0);
  transition:
    color 0.3s ease,
    background-color 0.3s ease,
    transform 0.3s ease;
}

.box:hover {
  color: #fff;
  background-color: #168bf5;
  transform: translateX(20px);
}

也可以使用 all

.box {
  transition: all 0.3s ease;
}

all 可能让不希望动画化的属性也参与过渡,维护和性能控制不如明确列出属性。

3. transition 语法

.box {
  transition: property duration timing-function delay;
}

更完整地说,transition 是以下长属性的简写:

长属性描述
transition-property指定参与过渡的 CSS 属性,例如 colortransformall
transition-duration过渡完成所需的时间,单位通常为 sms
transition-timing-function控制过渡过程中的速度曲线,例如 easelinearsteps()
transition-delay过渡开始前等待的时间,可以是负值

例如:

.box {
  transition-property: opacity, transform;
  transition-duration: 300ms, 500ms;
  transition-timing-function: ease, ease-out;
  transition-delay: 0ms, 100ms;
}

只有适合插值的属性才能产生连续过渡。颜色、长度、透明度和变换等属性通常适合过渡;某些离散属性只能在状态切换时直接改变。现代 CSS 也在逐步增加离散属性的过渡能力,但应结合目标浏览器支持情况使用。

二、animation:关键帧动画

1. animationtransition 的区别

animationtransition 都可以产生动画效果,但它们不是简单的包含关系,也不能把 animation 直接理解成多个 transition 的叠加。

  • transition 依赖计算值变化;
  • animation 依赖 @keyframes 定义的时间轴;
  • transition 通常用于状态变化;
  • animation 可以在没有交互的情况下自动运行;
  • animation 支持关键帧、循环、反向、暂停和结束后的样式保留。

2. 一个 animation 示例

<div class="box"></div>
.box {
  width: 100px;
  height: 100px;
  border: 15px solid #000;
  animation: changebox 1s ease-in-out 1s infinite alternate;
}

.box:hover {
  animation-play-state: paused;
}

@keyframes changebox {
  10% {
    background: red;
  }

  50% {
    width: 80px;
  }

  70% {
    border-color: yellow;
  }

  100% {
    width: 180px;
    height: 180px;
  }
}

在这个示例中:

  • changebox 是动画名称;
  • 1s 是每次播放的持续时间;
  • ease-in-out 是时间函数;
  • 第二个 1s 是延迟时间;
  • infinite 表示无限循环;
  • alternate 表示正向、反向交替播放;
  • 鼠标悬停时通过 animation-play-state: paused 暂停动画。

animation 关键帧动画效果

3. @keyframes 的时间百分比

@keyframes 定义一个动画组合,例如:

@keyframes changebox {
  0% {
    transform: translateX(0);
  }

  50% {
    transform: translateX(100px);
  }

  100% {
    transform: translateX(0);
  }
}

其中 0%50%100% 是动画有效时间轴上的位置。如果动画持续时间为 1s50% 对应有效播放区间中的 0.5s,而不是包含延迟时间在内的总时间。

如果没有显式声明 0%100%,浏览器会根据可用关键帧和元素动画前的样式推导起始或结束状态。关键帧之间的可动画属性会根据时间函数进行插值。

4. animation 语法

传统 animation 简写可以表示为:

.box {
  animation: name duration timing-function delay iteration-count direction fill-mode play-state;
}

它对应以下主要长属性:

长属性描述
animation-name要使用的 @keyframes 名称
animation-duration每次播放的持续时间
animation-timing-function控制关键帧区间中的插值速度
animation-delay动画开始前的等待时间,可以是负值
animation-iteration-count播放次数,可以是具体次数或 infinite
animation-direction播放方向,包括 normalreversealternatealternate-reverse
animation-play-state播放状态,包括 runningpaused
animation-fill-mode动画执行前后是否应用关键帧样式

简写中的关键字顺序在一定范围内可以调整,但两个时间值中第一个通常解析为 duration,第二个解析为 delay。为了便于阅读,建议按照上面的顺序书写。

5. animation-direction

描述
normal每次按照关键帧声明的顺序播放
reverse每次按照关键帧声明的反方向播放
alternate奇数次正向、偶数次反向播放
alternate-reverse奇数次反向、偶数次正向播放

6. animation-fill-mode

描述
none动画执行前后不应用动画关键帧之外的保持效果
forwards动画结束后保留最后一个有效关键帧的样式
backwardsdelay 延迟期间应用第一个有效关键帧的样式
both同时应用 backwardsforwards 的效果

注意:forwards 只有在动画正常结束后才有明显效果。如果设置了:

animation-iteration-count: infinite;

动画不会正常结束,因此 forwards 没有实际的结束时机;但 backwards 仍可能在延迟期间生效。

负延迟可以让动画从时间轴中间开始:

.box {
  animation-delay: -500ms;
}

这并不是先等待 500ms,而是表示动画开始时已经播放了一部分。

三、transform:变换

transform 用于改变元素的几何呈现方式,常见函数包括:

.box {
  transform: translate(20px, 10px);
}

.box {
  transform: rotate(45deg);
}

.box {
  transform: scale(1.2);
}

.box {
  transform: skewX(20deg);
}

多个变换函数可以组合:

.box {
  transform: translateX(100px) rotate(45deg) scale(1.2);
}

变换函数的顺序会影响最终结果,平移后旋转和旋转后平移通常不是相同的结果,因此不要随意调换顺序。

transform 的重要特点

  1. 通常只改变元素的视觉呈现,不会按照变换后的尺寸重新排列普通流中的兄弟元素;
  2. 可能影响元素的命中测试区域和溢出区域;
  3. transform 不为 none 时通常会创建层叠上下文;
  4. 可能成为绝对定位或固定定位后代的包含块;
  5. 经常用于位移、旋转、缩放动画,但不能因此绝对保证所有场景都具有更高性能;
  6. 默认情况下,变换围绕 transform-origin 进行。
.box {
  transform-origin: center;
  transform: rotate(30deg);
}

如果只是让元素在页面中占据新的布局位置,应根据需求使用 margin、布局属性或定位,而不是一律使用 transform

四、translate:平移

1. translate() 函数

translate()transform 中的平移函数:

.box {
  transform: translate(20px, 10px);
}

也可以使用:

.box {
  transform: translateX(20px);
}

.box {
  transform: translateY(10px);
}

.box {
  transform: translateZ(20px);
}

2. 独立的 translate 属性

现代 CSS 还提供了独立的 translate 变换属性:

.box {
  translate: 20px 10px;
}

它与下面的写法表达了相似的平移意图:

.box {
  transform: translate(20px, 10px);
}

但二者属于不同的 CSS 属性体系。独立的 translaterotatescale 属性可以分别控制变换,适合需要独立修改某一个变换分量的场景。使用前应确认目标浏览器支持情况。

五、transitionanimationtransformtranslate 对比

项目transitionanimationtransformtranslate
主要作用在两个计算值之间过渡按关键帧和时间轴播放描述几何变换描述平移变换
是否需要状态变化通常需要不一定需要本身不负责播放本身不负责播放
是否支持关键帧不支持显式关键帧支持 @keyframes不适用不适用
是否支持循环没有独立循环机制支持 iteration-count不适用不适用
是否可以暂停没有专用播放状态支持 animation-play-state不适用不适用
是否能改变布局通常不改变布局结构取决于动画的属性通常不改变普通流布局通常不改变普通流布局

常见组合如下:

.button {
  transform: translateY(0);
  transition: transform 200ms ease;
}

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

这里:

  • transform 定义按钮要移动到哪里;
  • transition 定义移动过程如何变化;
  • :hover 提供计算值变化的触发条件。

另一个例子:

.loading {
  animation: rotate 1s linear infinite;
}

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

这里:

  • transform 定义旋转变换;
  • @keyframes 定义从 0deg360deg 的时间轴;
  • animation 让这个时间轴持续循环播放。

六、CSS 动画与 JavaScript 动画

CSS 动画适合声明式的状态变化和循环效果;JavaScript 适合根据用户输入、物理计算、游戏逻辑或实时数据动态控制动画。

不要使用 setTimeoutsetInterval 简单地固定频率修改样式来代替所有动画。对于需要 JavaScript 驱动的视觉更新,通常可以使用 requestAnimationFrame

let frameId

function render(timestamp) {
  // 根据 timestamp 计算当前位置,并更新元素样式
  frameId = requestAnimationFrame(render)
}

frameId = requestAnimationFrame(render)

// 需要停止时:
// cancelAnimationFrame(frameId)

requestAnimationFrame 通常会让回调与浏览器绘制节奏更协调,但它并不保证回调中的代码一定高性能。频繁读取布局、强制同步布局、复杂计算和大量 DOM 更新仍然可能造成卡顿。

如果只是实现简单的渐变、位移、旋转或循环效果,优先考虑 CSS transitionanimation

七、无障碍与性能注意事项

1. 尊重用户的减少动态效果设置

部分用户会在系统中启用减少动态效果。可以使用媒体查询降低或取消动画:

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

具体项目也可以根据交互需求提供更合适的静态状态,而不是简单地让所有动画瞬间结束。

2. 选择适合动画的属性

位移、缩放、旋转和透明度经常适合做动画,但实际性能还与动画面积、设备、浏览器、阴影、滤镜和其他页面任务有关。不要仅凭属性名称绝对判断性能,应使用浏览器 Performance、Rendering 和 Layers 工具验证。

3. 避免无意义的 will-change

/* 不建议长期给大量元素设置 */
.box {
  will-change: transform;
}

will-change 只是性能提示,过度使用可能增加内存占用和渲染管理成本。通常应在确实需要时短时间使用,或先通过性能工具确认问题。

总结

  • transition 依赖计算值变化,在起始值和结束值之间产生过渡;
  • transition 可以同时处理多个属性,并不是只能处理一个属性;
  • animation 使用 @keyframes 和时间轴,可以自动播放、循环、反向和暂停;
  • transform 描述平移、旋转、缩放和倾斜等几何变换,本身不负责随时间播放;
  • translate()transform 中的平移函数;
  • translate 也可以作为现代 CSS 的独立变换属性;
  • transform 通常不会让普通流兄弟元素重新布局,但可能影响层叠上下文和定位包含块;
  • animation-fill-mode 中正确的拼写是 backwards
  • requestAnimationFrame 适合 JavaScript 驱动的视觉更新,但不等于所有代码都会自动高性能;
  • 简单状态过渡优先使用 transition,复杂时间轴和循环效果优先使用 animation
  • 动画设计应考虑性能和 prefers-reduced-motion

参考资料

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS