3、CSS动画入门:transition过渡、transform变换、animation动画、@keyframes关键帧、性能与硬件加速

好,咱们进入CSS动画的世界。说实话,CSS动画是我个人觉得性价比最高的跨平台方案——你不需要引入任何第三方库,浏览器原生支持,写起来也直观。我在早期做移动端H5的时候,很多交互动效就是用CSS搞定的,流畅度完全不输原生。

这一章,咱们把CSS动画的四个核心概念讲透:transitiontransformanimation@keyframes。最后再聊聊性能和硬件加速,这可是实战中的关键。

3.1 transition:最简单的过渡动画

transition 说白了就是「状态变化时的平滑过渡」。你想想看,一个按钮从红色变成蓝色,如果没有transition,它瞬间就变了,很生硬。加上transition,它就会慢慢过渡过去,视觉上舒服很多。

基本语法长这样:

/* 简写形式 */
transition: property duration timing-function delay;

/* 实际例子 */
.button {
  background-color: #ff6b6b;
  transition: background-color 0.3s ease;
}

.button:hover {
  background-color: #4ecdc4;
}

这里有几个参数要注意:

  • property:要过渡的属性,比如 background-coloropacitywidth 等。可以用 all 表示所有可过渡属性。
  • duration:过渡时长,单位秒(s)或毫秒(ms)。我个人习惯用 0.3s 作为默认值,视觉上不拖沓也不突兀。
  • timing-function:缓动函数,控制动画速度曲线。常用的有 easelinearease-inease-outease-in-out
  • delay:延迟多久开始过渡。
我的小技巧: 如果你想让多个属性以不同的速度过渡,可以这样写:transition: opacity 0.3s ease, transform 0.5s ease-out;。我在做卡片悬停效果时经常这么用,透明度先变,位置后变,层次感就出来了。

3.2 transform:变换的魔法

transform 不是动画本身,但它为动画提供了「变化的目标值」。你可以用它来平移、旋转、缩放、倾斜元素。

常用的变换函数:

函数 作用 示例
translate(x, y) 平移 transform: translate(50px, 100px)
rotate(deg) 旋转 transform: rotate(45deg)
scale(n) 缩放 transform: scale(1.5)
skew(deg) 倾斜 transform: skew(10deg, 5deg)

注意,transform 可以组合使用:

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

顺序很重要!translate 后再 rotaterotate 后再 translate,结果完全不同。嗯,这里要记住:变换是从右往左执行的。

我曾经踩过的坑:transform: translate(-50%, -50%) 做居中时,如果父容器没有明确的高度,百分比计算会出问题。后来我改用 flex 布局配合 margin: auto,稳多了。

3.3 animation + @keyframes:真正的动画

transition 只能处理「开始状态 → 结束状态」的简单变化。如果你想要更复杂的多阶段动画,就得用 animation 配合 @keyframes

@keyframes 定义动画的关键帧,animation 则控制动画如何播放。

/* 定义关键帧 */
@keyframes bounce {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-30px);
  }
  100% {
    transform: translateY(0);
  }
}

/* 应用动画 */
.ball {
  animation: bounce 1s ease-in-out infinite;
}

animation 的完整属性:

  • animation-name:关键帧名称
  • animation-duration:动画时长
  • animation-timing-function:缓动函数
  • animation-delay:延迟时间
  • animation-iteration-count:播放次数,infinite 表示无限循环
  • animation-direction:方向,normalreversealternate
  • animation-fill-mode:动画结束后保持的状态,forwards 保持最后一帧
  • animation-play-state:播放状态,runningpaused
实战经验: 我在做加载动画时,经常用 animation-delay 的负值来让多个元素错开播放。比如三个点依次弹跳,设置 animation-delay: -0.3s-0.6s,效果非常自然。

3.4 性能与硬件加速

好,这部分是重点。CSS动画虽然方便,但写不好照样卡成PPT。为什么?

浏览器渲染页面大致分几个阶段:JavaScript → Style → Layout → Paint → Composite。其中 Layout(重排)和 Paint(重绘)是最耗性能的。

哪些属性会触发重排?

  • widthheightmarginpaddingtopleft
  • display: noneblock

哪些只触发重绘?

  • colorbackground-colorvisibility

哪些只触发合成(最快)?

  • transformopacity

所以,我的建议是:能用 transformopacity 实现的动画,绝不用其他属性。比如移动一个元素,用 transform: translateX() 代替 left,性能差距巨大。

3.5 硬件加速:让GPU帮你干活

硬件加速,说白了就是让GPU(图形处理器)来分担CPU的渲染工作。CSS中可以通过 will-change 属性或 transform: translateZ(0) 来触发。

/* 告诉浏览器这个元素要变化,提前优化 */
.card {
  will-change: transform, opacity;
}

/* 或者用经典的 hack 方式 */
.card {
  transform: translateZ(0);
}
注意: will-change 不要滥用。我曾经在一个列表的每个元素上都加了 will-change: transform,结果内存占用飙升,反而更卡了。只在需要动画的元素上加,动画结束后最好移除。

硬件加速的原理是:浏览器会把元素提升到一个独立的合成层,由GPU单独处理。这样即使主线程卡顿,动画依然流畅。

但凡事都有代价——合成层过多会消耗GPU内存。移动端尤其敏感,有些低端机可能直接闪退。

3.6 实战建议总结

说了这么多,我总结几条实战中能直接用的原则:

  1. 简单交互用 transition:hover、focus、active 等状态变化,一行代码搞定。
  2. 复杂动画用 animation + @keyframes:多阶段、循环、带节奏的动画。
  3. 优先使用 transform 和 opacity:性能最好,不触发重排重绘。
  4. 谨慎使用 will-change:只在需要时加,用完记得移除。
  5. 测试低端设备:我在做项目时,经常用 Chrome 的 CPU 降速模拟来测试,调到 4x 或 6x 降速,卡不卡一目了然。

CSS动画入门其实不难,难的是写出既流畅又兼容的动画。下一章咱们会深入实战,看看怎么用CSS动画做出真正能用的UI动效。