@keyframes 是定义动画关键帧规则的CSS规则,本身不触发动画;animation 属性引用它并控制播放行为。必须命名合法、区分大小写,至少含 from 和 to 两帧,仅支持可动画属性,需配合 animation 才生效。

什么是 @keyframes?它和 animation 的关系是什么
@keyframes 本身不触发动画,它只是定义一组“关键帧规则”——也就是动画过程中某个时间点的样式快照。真正让元素动起来的是 animation 这个属性,它引用 @keyframes 名称并控制播放行为。
常见错误是只写了 @keyframes 却忘了给元素加 animation,结果页面完全没反应。
- 必须用合法标识符命名
@keyframes(比如slide-in、rotate-360),不能含空格或特殊符号 - 名称区分大小写,
myAnim和myanim是两个不同动画 -
浏览器会忽略未被
animation-name引用的@keyframes规则,不会预加载或解析
怎么写一个最简可用的 @keyframes 动画
最少需要两个关键帧:from(等价于 0%)和 to(等价于 100%)。中间可以加任意百分比帧,但不能少于两个。
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.element {
animation: fade-in 0.3s ease-out;
}
注意:from/to 写法更易读,但一旦要控制中间状态(比如在 50% 处停顿或反向),就必须用百分比写法。
立即学习“前端免费学习笔记(深入)”;
- 不能在
@keyframes中使用伪类(如:hover)、伪元素(如::before)或媒体查询 - 只能声明可动画的 CSS 属性(如
opacity、transform、color),display、height(非transform缩放)这类会触发布局重排的属性效果差且卡顿 - 推荐优先用
transform和opacity,它们能走合成层,性能更好
animation 属性里哪些参数最容易配错
单独写 animation: fade-in 0.5s; 看似简单,但实际漏掉关键参数会导致行为不符合预期。最常出问题的是以下三个:
-
animation-fill-mode:默认是none,动画结束立刻回退到初始样式。想要保持最后一帧,得显式写forwards -
animation-iteration-count:默认是1,不是无限循环。要循环必须写infinite或具体数字 -
animation-direction:默认是normal,来回播放需设为alternate,否则第二次播放还是从头开始
完整常用写法示例:
.box {
animation: slide-in 0.4s ease-in-out 0.2s 2 forwards alternate;
}
/* 顺序:name | duration | timing-function | delay | count | fill-mode | direction */为什么动画没生效?几个真实场景排查点
不是代码语法错,而是上下文踩坑。这些情况不会报错,但动画就是不动:
- 父容器有
overflow: hidden,而动画位移超出了可视区,看起来像“消失”了 - 元素初始状态和
from帧完全一致,浏览器可能跳过渲染(尤其transform: translateX(0)这种)——试试把from改成translateX(-1px)测试是否触发 - 用了
display: none切换显示,但display不可动画,应改用opacity: 0+visibility: hidden配合animation-fill-mode: forwards - 在 Vue/React 组件中动态添加 class,但 class 添加时机早于 DOM 挂载完成,导致动画未捕获初始状态——可加
setTimeout(() => ..., 0)或用requestAnimationFrame延迟触发
复杂动画别堆在单个 @keyframes 里,拆成多个小动画 + animation-delay 控制节奏更可控,也更容易复用和调试。










