2、关键帧魔法:@keyframes规则深度解析,从from/to到百分比控制,创建多阶段复杂动画

好,咱们直接进入正题。上一章我们聊了聊CSS动画的基本概念,知道了animation属性怎么用。但说实话,那些简单的动画——比如一个方块从左移到右——其实挺无聊的。真正让CSS动画变得强大、变得有灵魂的,是@keyframes这个规则。

我个人习惯把@keyframes叫做「动画剧本」。你想想看,一部电影如果没有剧本,演员怎么演?动画也一样。你得告诉浏览器:在什么时间点,元素应该变成什么样子。这就是@keyframes干的事。

2.1 从最简单的开始:from 和 to

先看一个最基础的写法:

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

这个动画很简单:从完全透明(opacity: 0)到完全不透明(opacity: 1)。from就是动画开始时的状态,to就是结束时的状态。说白了,这就是一个「两帧动画」。

我在项目中遇到过不少新手,觉得fromto只能写一个属性。其实不是的,你可以写多个:

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

这样元素就会一边移动一边淡入。嗯,效果还不错。

小技巧:如果你只写了 to 没写 from,浏览器会默认使用元素的当前样式作为起始状态。反过来也一样。但为了代码可读性,我建议还是都写上。

2.2 真正的控制力:百分比控制

fromto虽然简单,但只能控制两个时间点。如果你想做更复杂的动画——比如一个弹跳效果,或者一个多阶段变色——那就得用百分比了。

百分比代表的是动画总时长的百分比。比如动画时长是2秒,那50%就对应第1秒的位置。

来看一个弹跳球的例子:

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

这个动画模拟了球落地后弹起、再落下的过程。你看,通过多个百分比节点,我们就能控制球在不同时间点的位置。这就是多阶段动画的核心思想。

我曾经做过一个加载动画,需要让一个圆环先旋转、再变色、再缩放。如果用from/to,我得写三个动画。但用百分比,一个@keyframes就搞定了:

@keyframes loader {
  0% {
    transform: rotate(0deg) scale(1);
    border-color: #3498db;
  }
  33% {
    transform: rotate(120deg) scale(1.2);
    border-color: #e74c3c;
  }
  66% {
    transform: rotate(240deg) scale(0.8);
    border-color: #2ecc71;
  }
  100% {
    transform: rotate(360deg) scale(1);
    border-color: #3498db;
  }
}
核心要点:百分比不是必须从0%开始、到100%结束。你可以只写30%和70%,浏览器会自动把0%和100%当作元素的初始状态。但为了清晰,我建议还是显式写出0%和100%。

2.3 百分比 vs from/to:怎么选?

这个问题其实很简单。我个人的经验是:

  • 只有两个状态:用from/to,代码更简洁
  • 三个及以上状态:用百分比,控制更精细
  • 需要精确控制时间点:用百分比,比如25%50%75%

但说实话,我后来基本只用百分比了。为什么?因为万一以后要加一个中间状态,from/to就得改成百分比,麻烦。直接用百分比,一劳永逸。

2.4 避坑指南:我曾经踩过的坑

嗯,这里得说说我当年犯过的错。有一次我做了一个复杂的动画,用了十几个百分比节点。结果动画跑起来卡得要命。排查了半天,发现是百分比节点太多,而且每个节点都改变了box-shadowfilter这些重绘属性

所以这里给大家几个建议:

  1. 百分比节点不是越多越好。一般3-5个节点就能做出很流畅的动画了。
  2. 避免在关键帧中频繁改变重绘属性(比如box-shadowfilterborder-radius)。尽量用transformopacity,这两个属性由GPU处理,性能最好。
  3. 百分比要合理分布。比如你想做一个「慢-快-慢」的效果,可以在20%80%处设置关键帧,而不是均匀分布。
警告:不同浏览器对@keyframes的解析可能有细微差异。特别是百分比值,有些老版本浏览器不支持小数百分比(比如33.33%)。为了兼容,尽量使用整数百分比。

2.5 实战:一个多阶段按钮动画

光说不练假把式。咱们来写一个实际点的例子——一个按钮的悬停动画。这个动画分三个阶段:

  • 第一阶段(0%-30%):按钮背景色渐变,同时轻微放大
  • 第二阶段(30%-70%):按钮颜色稳定,开始出现阴影
  • 第三阶段(70%-100%):阴影加深,按钮恢复原始大小
@keyframes buttonHover {
  0% {
    background: #3498db;
    transform: scale(1);
    box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  }
  30% {
    background: #2980b9;
    transform: scale(1.05);
    box-shadow: 0 4px 10px rgba(0,0,0,0.3);
  }
  70% {
    background: #2980b9;
    transform: scale(1.05);
    box-shadow: 0 6px 15px rgba(0,0,0,0.4);
  }
  100% {
    background: #3498db;
    transform: scale(1);
    box-shadow: 0 2px 5px rgba(0,0,0,0.2);
  }
}

.button {
  animation: buttonHover 0.6s ease-in-out;
}

你看,通过三个百分比节点,我们就实现了一个有「起承转合」的动画。比单纯的from/to丰富多了吧?

2.6 总结一下

@keyframes是CSS动画的灵魂。掌握了它,你就能做出各种复杂的动画效果。记住几个关键点:

特性 说明
from/to 两帧动画,简单直接
百分比 多帧动画,精细控制
性能 优先使用transform和opacity
兼容性 使用整数百分比,避免小数

下一章,我们会聊聊animation属性的其他参数——比如easingdelayiteration-count这些。你会发现,光有@keyframes还不够,还得配合这些参数才能做出真正丝滑的动画。

好,今天就到这儿。去试试自己写一个多阶段的@keyframes吧,相信我,你会爱上这种感觉的。