3、CSS关键帧动画:@keyframes规则、animation属性、动画循环与方向控制
说实话,CSS动画是我在页面切换实战中最常用的技术之一。它不像JavaScript动画那样需要处理复杂的回调,也不依赖任何第三方库。你只需要写好@keyframes,再配上animation属性,一个流畅的页面过渡效果就出来了。
我记得刚入行那会儿,总觉得CSS动画是“玩具”,做不了复杂效果。直到有一次做移动端H5的页面切换,用JS动画在低端机上卡得不行,换成CSS关键帧动画后,丝般顺滑。从那以后,我对它的态度彻底变了。
3.1 @keyframes规则:动画的“剧本”
@keyframes说白了就是定义动画每一帧的样子。你告诉浏览器:从什么状态变到什么状态,中间怎么变,浏览器自己算。
基本写法有两种:
/* 方式一:from/to 关键词 */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 方式二:百分比节点(更灵活) */
@keyframes slideIn {
0% {
opacity: 0;
transform: translateX(-100%);
}
50% {
opacity: 0.5;
transform: translateX(10%);
}
100% {
opacity: 1;
transform: translateX(0);
}
}
我个人习惯用百分比写法。为什么?因为你可以插入中间状态,做更细腻的效果。比如一个弹入动画,先过冲再回弹,用from/to就做不到。
@keyframes fadeIn 和 @keyframes fadeOut,命名清晰,维护起来也方便。
3.2 animation属性:把剧本搬上舞台
光有@keyframes还不够,你得用animation属性把它“挂”到元素上。这个属性是个简写,背后有8个子属性。我刚开始学的时候也觉得多,但用熟了发现,常用的其实就那几个。
| 子属性 | 作用 | 默认值 |
|---|---|---|
animation-name |
指定@keyframes名称 | none |
animation-duration |
动画时长 | 0s |
animation-timing-function |
速度曲线 | ease |
animation-delay |
延迟启动 | 0s |
animation-iteration-count |
播放次数 | 1 |
animation-direction |
播放方向 | normal |
animation-fill-mode |
结束状态保持 | none |
animation-play-state |
播放/暂停 | running |
简写示例:
.page-enter {
animation: slideIn 0.6s ease-out 0.2s 1 normal forwards;
}
这个写法顺序是:名称、时长、速度曲线、延迟、次数、方向、填充模式。记不住顺序也没关系,我写代码时经常只写前两个,其他的按需追加。
animation-fill-mode: forwards 在页面切换中特别有用。它让动画结束后保持最后一帧的状态,不会“闪回”到初始位置。我见过不少新手因为忘了这个,页面切完后元素突然跳回原位。
3.3 动画循环:一次、两次还是无限?
animation-iteration-count控制播放次数。取值很简单:
- 数字:比如
2表示播放两次,3.5表示三次半 - infinite:无限循环
页面切换动画通常用 1 次就够了。但有些场景需要循环,比如加载中的转圈动画:
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.loading-spinner {
animation: spin 1s linear infinite;
}
我曾经犯过一个错:给页面退出动画设了 infinite。结果页面切走后,那个退出动画一直在后台循环,CPU占用直接拉满。嗯,这个坑你们别踩。
3.4 方向控制:正着放、倒着放、来回放
animation-direction有四个值,我列个表对比一下:
| 值 | 行为 | 适用场景 |
|---|---|---|
normal |
从0%到100%正常播放 | 页面进入动画 |
reverse |
从100%到0%反向播放 | 页面退出动画 |
alternate |
先正后反,来回交替 | 悬停呼吸效果 |
alternate-reverse |
先反后正,来回交替 | 与alternate起始方向相反 |
这里有个实用技巧:页面进入和退出可以用同一个@keyframes,只改方向。比如:
/* 同一个关键帧 */
@keyframes slideUp {
from { transform: translateY(100%); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
/* 进入:正常播放 */
.page-in {
animation: slideUp 0.4s ease-out forwards;
}
/* 退出:反向播放,效果就是滑出屏幕 */
.page-out {
animation: slideUp 0.4s ease-in reverse forwards;
}
这样做的好处是少写一套@keyframes,代码更干净。我在做页面切换框架时,经常用这个模式。
reverse 和 alternate 配合 animation-timing-function 时要小心。比如 ease-in 反向播放后实际效果变成了 ease-out。如果你需要精确控制,建议单独写退出关键帧。
3.5 知识体系总览
下面这张图是我自己梳理的CSS关键帧动画知识结构,你可以把它当做一个快速索引:
3.6 实战中的避坑指南
最后分享几个我踩过的坑:
- 动画不生效? 先检查
animation-name和@keyframes的名字是否一致。我至少有三四次因为拼写错误找了半天。 - 动画闪一下? 八成是忘了
forwards。加上animation-fill-mode: forwards就好了。 - 页面切换卡顿? 尽量用
transform和opacity做动画,别用left/top/width/height。前者由GPU加速,后者触发重排。 - 多个动画冲突? 一个元素可以同时挂多个动画,用逗号分隔:
animation: fadeIn 0.3s, slideIn 0.5s。但要注意时间配合。
嗯,CSS关键帧动画的核心内容就这些。你把它理解成“定义动作 + 控制播放”,后面做页面切换时就会很顺手。