文章目录
-
- [一、什么是 `@keyframes`?](#一、什么是
@keyframes?) -
- [1.1 基本语法](#1.1 基本语法)
- [1.2 应用动画](#1.2 应用动画)
- [二、`animation` 八大属性详解](#二、
animation八大属性详解) -
- [⚠️ 重要规范:`animation` 简写的最小有效形式](#⚠️ 重要规范:
animation简写的最小有效形式) - [2.1 `animation-name`](#2.1
animation-name) - [2.2 `animation-duration`](#2.2
animation-duration) - [2.3 `animation-timing-function`](#2.3
animation-timing-function) - [2.4 `animation-delay`](#2.4
animation-delay) - [2.5 `animation-iteration-count`](#2.5
animation-iteration-count) - [2.6 `animation-direction`](#2.6
animation-direction) - [2.7 `animation-fill-mode`](#2.7
animation-fill-mode) - [2.8 `animation-play-state`](#2.8
animation-play-state)
- [⚠️ 重要规范:`animation` 简写的最小有效形式](#⚠️ 重要规范:
- 三、性能与最佳实践
-
- [3.1 仅动画合成属性](#3.1 仅动画合成属性)
- [3.2 响应用户偏好](#3.2 响应用户偏好)
- [3.3 调试工具](#3.3 调试工具)
- 四、常见错误与解决方案
- [一、什么是 `@keyframes`?](#一、什么是
一、什么是 @keyframes?
@keyframes 是 CSS 中用于定义动画关键帧序列的规则。它描述了一个元素在动画过程中,其样式如何随时间变化。
与 transition(仅支持起止两点)不同,@keyframes 支持:
- 多个中间状态(如 0% → 30% → 70% → 100%)
- 循环播放
- 方向控制
- 精确的时间轴定义
1.1 基本语法
css
@keyframes animation-name {
from { /* 起始样式 */ }
to { /* 结束样式 */ }
}
或使用百分比(更灵活):
css
@keyframes slideIn {
0% { transform: translateX(-100px); opacity: 0; }
100% { transform: translateX(0); opacity: 1; }
}
✅ 规范说明(CSS Animations §3.1):
from等价于0%,to等价于100%- 关键帧顺序在源码中可任意排列,浏览器按百分比数值自动排序
- 若未定义
0%或100%,浏览器会自动推断缺失端点(取元素当前计算样式)
加alternate: 0% → 100% → 0%
1.2 应用动画
仅定义 @keyframes 不会产生效果。必须通过 animation 属性将其绑定到元素:
css
.element {
animation: slideIn 0.4s ease-out forwards;
}
二、animation 八大属性详解
CSS 定义了 8 个独立属性,共同控制动画行为。它们既可分开书写,也可通过 animation 简写合并(但 animation-play-state 除外)。
⚠️ 重要规范:animation 简写的最小有效形式
根据 W3C CSS Animations Level 1 §4:
- 在
animation简写中,只有animation-name和animation-duration是逻辑上必需的 - 实际最小可见 动画必须包含
name+duration - 若只写名称(如
animation: fadeIn;),则duration使用默认值0s,动画瞬间完成,肉眼不可见 - 浏览器按固定顺序解析简写值:
<animation-name>- 第一个
<time>→duration - 第二个
<time>→delay <timing-function><iteration-count><direction><fill-mode>
animation-play-state永远不会被简写解析,必须单独声明
✅ 正确示例:
css
/* 最小有效(可见)动画 */
.element { animation: slideIn 0.4s; }
/* 完整控制 */
.element { animation: bounce 0.6s ease-in 0.1s infinite alternate forwards; }
❌ 常见错误:
css
/* 错误:只写名称 → duration = 0s → 动画不可见 */
.element { animation: fadeIn; }
2.1 animation-name
- 作用 :指定要应用的
@keyframes名称 - 默认值 :
none - 是否可简写:✅ 是
典型用法
css
.element {
animation-name: fadeIn;
}
/* 多动画叠加 */
.element {
animation-name: float, pulse;
animation-duration: 3s, 2s;
animation-iteration-count: infinite, infinite;
}
工程提示
- 名称拼错或未定义 → 动画静默失效(无报错)
- 名称区分大小写
2.2 animation-duration
- 作用:单次动画循环的持续时间
- 默认值 :
0s(动画瞬间完成,不可见) - 是否可简写:✅ 是
典型用法
css
.button:hover {
animation: ripple 0.2s linear;
}
.modal {
animation: slideIn 0.4s ease-out forwards;
}
工程提示
- 必须带单位 :
animation-duration: 1;❌ 无效 - 推荐时长:
- 微交互:
150ms -- 300ms - 页面动效:
300ms -- 600ms
- 微交互:
- 避免 >1s(用户感知为卡顿)
2.3 animation-timing-function
- 作用:定义关键帧之间的速度变化曲线(缓动函数)
- 默认值 :
ease - 是否可简写:✅ 是
常用值说明
| 值 | 说明 |
|---|---|
linear |
匀速运动,无加速/减速,机械感强(适合进度条、跑马灯) |
ease |
默认缓动:快入慢出(类似 ease-out,但起始稍缓) |
ease-in |
慢启动 → 快结束,模拟物体从静止开始加速 |
ease-out |
快启动 → 慢停止,最常用,模拟自然减速停稳 |
ease-in-out |
慢 → 快 → 慢,适合对称动画(如呼吸、弹跳) |
cubic-bezier(x1,y1,x2,y2) |
自定义贝塞尔曲线,可实现弹性、过冲等高级效果 |
step-start |
动画开始瞬间跳到最终状态(0% → 100% 无过渡) |
step-end |
动画结束瞬间才变化(常用于打字机、帧动画) |
steps(5) 或 steps(5, end) |
分 5 步完成,中间无渐变;第二参数可选 start/end(默认 end) |
典型用法
css
.card {
animation: popIn 0.5s cubic-bezier(0.68, -0.55, 0.27, 1.55) forwards;
}
.typewriter {
animation: type 2s steps(20, end) forwards;
}
@keyframes type {
to { width: 100%; }
}
工程提示
- 使用 cubic-bezier.com 可视化生成曲线
steps()适用于 sprite 动画或逐字显示
2.4 animation-delay
- 作用:动画开始前的等待时间
- 默认值 :
0s - 是否可简写:✅ 是
典型用法
css
/* 错峰出场 */
.item:nth-child(1) { animation-delay: 0.0s; }
.item:nth-child(2) { animation-delay: 0.1s; }
/* 负延迟:跳过开头 */
.synced {
animation: myAnim 1s ease-out -0.3s;
}
工程提示
- 负值表示"从动画中间开始"
delay期间元素保持原始样式,除非设置fill-mode: backwards
2.5 animation-iteration-count
- 作用:动画播放次数
- 默认值 :
1 - 是否可简写:✅ 是
常用值说明
| 值 | 说明 |
|---|---|
1 |
播放 1 次(默认) |
3 |
播放 3 次 |
infinite |
无限循环(⚠️ 注意性能与无障碍) |
典型用法
css
.spinner {
animation: rotate 1s linear infinite;
}
.alert {
animation: blink 0.5s ease-in-out 3;
}
工程提示
infinite动画在后台仍可能运行 → 建议监听visibilitychange暂停- 必须响应
prefers-reduced-motion:
css
@media (prefers-reduced-motion: reduce) {
.spinner { animation: none; }
}
2.6 animation-direction
- 作用:控制每次迭代的播放方向
- 默认值 :
normal - 是否可简写:✅ 是
常用值说明
| 值 | 说明 |
|---|---|
normal |
每次均 0% → 100% |
reverse |
每次均 100% → 0% |
alternate |
奇数次 0%→100%,偶数次 100%→0%(来回摆动) |
alternate-reverse |
奇数次 100%→0%,偶数次 0%→100% |
典型用法
css
.pendulum {
animation: swing 1s ease-in-out infinite alternate;
}
@keyframes swing {
0% { transform: rotate(-15deg); }
100% { transform: rotate(15deg); }
}
工程提示
alternate是实现"自然摆动"的最简方式- 对
iteration-count: 1无效(等同于normal)
2.7 animation-fill-mode
- 作用 :控制动画之外(开始前 / 结束后)的样式状态
- 默认值 :
none - 是否可简写:✅ 是
常用值说明
| 值 | 说明 |
|---|---|
none |
默认行为:动画结束后恢复原始 CSS 样式(易导致"闪回") |
forwards |
保持最后一帧状态(⭐ 淡入/滑入后必须用!) |
backwards |
在 delay 期间就应用第一帧样式(避免 delay 时显示未初始化状态) |
both |
同时启用 forwards + backwards |
典型用法
css
/* 正确:淡入后保持可见 */
.modal {
opacity: 0;
animation: fadeIn 0.3s ease-out forwards;
}
@keyframes fadeIn {
to { opacity: 1; }
}
/* 错误:动画结束后消失! */
.modal-wrong {
opacity: 0;
animation: fadeIn 0.3s ease-out; /* 缺少 forwards */
}
工程提示
- 凡是用于"显示/隐藏"类动画,几乎 always 用
forwards backwards常与delay配合使用
2.8 animation-play-state
- 作用:控制动画当前是运行还是暂停
- 默认值 :
running - 是否可简写 :❌ 否!必须单独声明
典型用法
css
/* 悬停暂停 */
.rotating-icon {
animation: rotate 2s linear infinite;
}
.rotating-icon:hover {
animation-play-state: paused;
}
/* 焦点暂停背景 */
input:focus ~ .bubbles {
animation-play-state: paused;
}
工程提示
-
暂停时时间线冻结,恢复后继续(不重置)
-
性能极佳:不触发重排/重绘
-
可被 JavaScript 动态控制:
jsel.style.animationPlayState = document.hidden ? 'paused' : 'running'; -
常用于悬停查看、节能、减少干扰
三、性能与最佳实践
3.1 仅动画合成属性
为保证 60fps 流畅度,只应动画以下属性:
transform(translate,scale,rotate)opacity
✅ 这两类属性由 GPU 合成,不触发 Layout/Paint
❌ 避免:
width,height,top,left,margin,padding,font-size
3.2 响应用户偏好
尊重无障碍设置:
css
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
✅ 符合 WCAG 2.1 AA 标准
3.3 调试工具
Chrome DevTools → Elements → 选中元素 → Styles 中点击 animation 旁 🎞️ 图标
→ 可逐帧查看、减速、导出动画
四、常见错误与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 动画无效果 | duration 为 0 或名称拼错 |
检查 animation-duration > 0 和 name 匹配 |
| 动画结束后元素消失 | 未设 fill-mode: forwards |
添加 forwards |
| 卡顿掉帧 | 动画了非合成属性 | 改用 transform / opacity |
| 无限循环耗电 | 未处理后台标签页 | 监听 visibilitychange 暂停动画 |
| 多动画错乱 | animation 简写中属性数量不匹配 |
确保各子属性数量与动画名数量一致 |
play-state 无效 |
写进了 animation 简写 |
必须单独写:animation-play-state: paused; |
| 动画看不见 | 只写了 animation: name; |
补全 duration:animation: name 0.3s; |