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就是结束时的状态。说白了,这就是一个「两帧动画」。
我在项目中遇到过不少新手,觉得from和to只能写一个属性。其实不是的,你可以写多个:
@keyframes slideAndFade {
from {
opacity: 0;
transform: translateX(-100px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
这样元素就会一边移动一边淡入。嗯,效果还不错。
to 没写 from,浏览器会默认使用元素的当前样式作为起始状态。反过来也一样。但为了代码可读性,我建议还是都写上。
2.2 真正的控制力:百分比控制
from和to虽然简单,但只能控制两个时间点。如果你想做更复杂的动画——比如一个弹跳效果,或者一个多阶段变色——那就得用百分比了。
百分比代表的是动画总时长的百分比。比如动画时长是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;
}
}
2.3 百分比 vs from/to:怎么选?
这个问题其实很简单。我个人的经验是:
- 只有两个状态:用
from/to,代码更简洁 - 三个及以上状态:用百分比,控制更精细
- 需要精确控制时间点:用百分比,比如
25%、50%、75%
但说实话,我后来基本只用百分比了。为什么?因为万一以后要加一个中间状态,from/to就得改成百分比,麻烦。直接用百分比,一劳永逸。
2.4 避坑指南:我曾经踩过的坑
嗯,这里得说说我当年犯过的错。有一次我做了一个复杂的动画,用了十几个百分比节点。结果动画跑起来卡得要命。排查了半天,发现是百分比节点太多,而且每个节点都改变了box-shadow和filter这些重绘属性。
所以这里给大家几个建议:
- 百分比节点不是越多越好。一般3-5个节点就能做出很流畅的动画了。
- 避免在关键帧中频繁改变重绘属性(比如
box-shadow、filter、border-radius)。尽量用transform和opacity,这两个属性由GPU处理,性能最好。 - 百分比要合理分布。比如你想做一个「慢-快-慢」的效果,可以在
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属性的其他参数——比如easing、delay、iteration-count这些。你会发现,光有@keyframes还不够,还得配合这些参数才能做出真正丝滑的动画。
好,今天就到这儿。去试试自己写一个多阶段的@keyframes吧,相信我,你会爱上这种感觉的。