pin_drop当前位置:知识文库 ❯ 图文
CSS集成:CSS动画详解 - @keyframes与animation属性完整指南
一、教程简介
CSS animation 属性结合 @keyframes 规则,可以创建复杂的连续动画效果,无需 JavaScript 即可实现旋转、弹跳、淡入淡出等丰富动画。与 transition 只能在状态变化时触发不同,animation 可以自动播放、循环播放,并精确控制动画的每个关键帧。本教程将详细讲解 CSS 动画的语法、关键帧、子属性以及实战应用。
二、核心概念
@keyframes 语法
代码示例
/* 基本语法 */
@keyframes animationName {
from { /* 起始状态 */ }
to { /* 结束状态 */ }
}
/* 百分比关键帧 */
@keyframes animationName {
0% { /* 起始状态 */ }
25% { /* 25%时刻 */ }
50% { /* 中间状态 */ }
75% { /* 75%时刻 */ }
100% { /* 结束状态 */ }
}
/* 示例:弹跳动画 */
@keyframes bounce {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-30px); }
}
/* 示例:旋转动画 */
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}animation 简写属性
代码示例
/* 完整简写 */
animation: name duration timing-function delay iteration-count direction fill-mode play-state;
/* 示例 */
animation: bounce 1s ease 0s infinite alternate forwards running;
/* 常用简写 */
animation: spin 2s linear infinite;animation 子属性
代码示例
/* 动画名称 */
animation-name: bounce;
/* 动画时长 */
animation-duration: 1s;
animation-duration: 500ms;
/* 时序函数 */
animation-timing-function: ease;
animation-timing-function: linear;
animation-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
/* 延迟 */
animation-delay: 0.2s;
/* 播放次数 */
animation-iteration-count: 1; /* 播放1次 */
animation-iteration-count: 3; /* 播放3次 */
animation-iteration-count: infinite; /* 无限循环 */
/* 播放方向 */
animation-direction: normal; /* 正向 */
animation-direction: reverse; /* 反向 */
animation-direction: alternate; /* 正反交替 */
animation-direction: alternate-reverse; /* 反正交替 */
/* 填充模式 */
animation-fill-mode: none; /* 不填充 */
animation-fill-mode: forwards; /* 保持结束状态 */
animation-fill-mode: backwards; /* 应用起始状态 */
animation-fill-mode: both; /* 同时应用 */
/* 播放状态 */
animation-play-state: running; /* 播放 */
animation-play-state: paused; /* 暂停 */多动画
代码示例
/* 同时应用多个动画 */
animation: spin 2s linear infinite, pulse 1.5s ease infinite;
/* 分开写法 */
animation-name: spin, pulse;
animation-duration: 2s, 1.5s;
animation-timing-function: linear, ease;
animation-iteration-count: infinite, infinite;三、代码示例
示例1:基础动画效果
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>基础动画效果</title>
<style>
/* 旋转 */
@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
.anim-spin .box { animation: spin 2s linear infinite; }
/* 弹跳 */
@keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-25px); } }
.anim-bounce .box { animation: bounce 1s ease infinite; }
/* 脉冲 */
@keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.15); opacity: 0.8; } }
.anim-pulse .box { animation: pulse 1.5s ease infinite; }
/* 摇晃 */
@keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-8px); } 75% { transform: translateX(8px); } }
.anim-shake .box { animation: shake 0.5s ease infinite; }
/* 淡入淡出 */
@keyframes fadeIO { 0%, 100% { opacity: 1; } 50% { opacity: 0.2; } }
.anim-fade .box { animation: fadeIO 2s ease infinite; }
/* 翻转 */
@keyframes flip { 0% { transform: perspective(400px) rotateY(0); } 100% { transform: perspective(400px) rotateY(360deg); } }
.anim-flip .box { animation: flip 2s ease-in-out infinite; }
</style>
</head>
<body>
<h1>基础动画效果</h1>
<div class="demo-grid">
<div class="demo-card anim-spin"><div class="box"></div><h3>旋转</h3></div>
<div class="demo-card anim-bounce"><div class="box"></div><h3>弹跳</h3></div>
<div class="demo-card anim-pulse"><div class="box"></div><h3>脉冲</h3></div>
<div class="demo-card anim-shake"><div class="box"></div><h3>摇晃</h3></div>
<div class="demo-card anim-fade"><div class="box"></div><h3>淡入淡出</h3></div>
<div class="demo-card anim-flip"><div class="box"></div><h3>翻转</h3></div>
</div>
</body>
</html>示例2:animation-fill-mode与direction
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>fill-mode与direction</title>
<style>
@keyframes moveRight {
from { transform: translateX(0); background: #3498db; }
to { transform: translateX(300px); background: #e74c3c; }
}
.fill-none .ball { animation: moveRight 2s ease none; }
.fill-forwards .ball { animation: moveRight 2s ease forwards; }
.fill-backwards .ball { animation: moveRight 2s ease 1s backwards; }
.fill-both .ball { animation: moveRight 2s ease 1s both; }
.dir-normal .ball { animation: moveRight 2s ease infinite normal; }
.dir-reverse .ball { animation: moveRight 2s ease infinite reverse; }
.dir-alternate .ball { animation: moveRight 2s ease infinite alternate; }
.dir-alt-reverse .ball { animation: moveRight 2s ease infinite alternate-reverse; }
</style>
</head>
<body>
<h1>fill-mode 与 direction</h1>
<h2>animation-fill-mode</h2>
<div class="fill-none"><div class="track"><div class="ball"></div></div></div>
<div class="fill-forwards"><div class="track"><div class="ball"></div></div></div>
<h2>animation-direction</h2>
<div class="dir-normal"><div class="track"><div class="ball"></div></div></div>
<div class="dir-alternate"><div class="track"><div class="ball"></div></div></div>
</body>
</html>示例3:动画实战应用
代码示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动画实战应用</title>
<style>
/* 加载动画 */
@keyframes spin { to { transform: rotate(360deg); } }
.loader-spinner { border: 4px solid #ecf0f1; border-top-color: #3498db; border-radius: 50%; animation: spin 0.8s linear infinite; }
@keyframes dotBounce { 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; } 40% { transform: scale(1); opacity: 1; } }
.loader-dots span { animation: dotBounce 1.4s ease-in-out infinite; }
.loader-dots span:nth-child(2) { animation-delay: 0.16s; }
.loader-dots span:nth-child(3) { animation-delay: 0.32s; }
@keyframes barSlide { 0% { transform: translateX(-100%); } 100% { transform: translateX(350%); } }
.loader-bar::after { animation: barSlide 1.2s ease infinite; }
/* 通知动画 */
@keyframes slideInRight { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
.notification { animation: slideInRight 0.4s ease forwards; }
/* 打字机效果 */
@keyframes typewriter { from { width: 0; } to { width: 100%; } }
@keyframes blink { 50% { border-color: transparent; } }
.typewriter-text { animation: typewriter 3s steps(20) 0.5s forwards, blink 0.7s step-end infinite; }
/* 浮动动画 */
@keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
.float-item { animation: float 3s ease-in-out infinite; }
.float-item:nth-child(2) { animation-delay: 0.5s; }
.float-item:nth-child(3) { animation-delay: 1s; }
</style>
</head>
<body>
<div class="container">
<h1>动画实战应用</h1>
<div class="section">
<h2>加载动画</h2>
<div class="loader-spinner"></div>
<div class="loader-dots"><span></span><span></span><span></span></div>
<div class="loader-bar"></div>
</div>
<div class="section">
<h2>通知滑入动画</h2>
<div class="notification notif-success">操作成功!</div>
</div>
<div class="section">
<h2>打字机效果</h2>
<div class="typewriter-text">Hello, CSS Animation World!</div>
</div>
<div class="section">
<h2>浮动图标</h2>
<div class="float-item">A</div>
<div class="float-item">B</div>
</div>
</div>
</body>
</html>提示:尊重用户的无障碍偏好,使用
@media (prefers-reduced-motion: reduce)为需要减少动画的用户提供替代方案。
四、浏览器兼容性
五、注意事项与最佳实践
注意事项
-
性能优先:动画属性优先使用
transform和opacity,避免触发重排 -
will-change:对频繁动画的元素添加
will-change: transform提示浏览器优化 -
动画暂停:使用
animation-play-state: paused暂停动画而非销毁重建 -
prefers-reduced-motion:尊重用户的无障碍偏好设置
-
关键帧顺序:
0%可省略(使用元素初始样式),但100%不可省略
最佳实践
-
命名规范:动画名称使用语义化命名,如
fadeIn、slideInLeft -
时长控制:UI 反馈动画 0.2-0.5s,装饰动画 1-3s,避免过长
-
循环动画:无限循环动画应尽量简单,避免消耗过多性能
-
动画延迟:利用
animation-delay创建错落效果 -
GPU加速:对动画元素使用
transform: translateZ(0)开启GPU加速
六、代码规范示例
不推荐的写法
代码示例
/* 不推荐:动画触发重排 */
@keyframes bad {
0% { width: 100px; height: 100px; }
100% { width: 200px; height: 200px; }
}
/* 不推荐:过长的动画时长 */
.box { animation: fadeIn 5s ease; }
/* 不推荐:忽略无障碍偏好 */
.box { animation: spin 1s linear infinite; }推荐的写法
代码示例
/* 推荐:使用transform替代 */
@keyframes good {
0% { transform: scale(1); }
100% { transform: scale(2); }
}
/* 推荐:合理的动画时长 */
.box { animation: fadeIn 0.3s ease; }
/* 推荐:尊重用户偏好 */
.box { animation: spin 1s linear infinite; }
@media (prefers-reduced-motion: reduce) {
.box { animation: none; }
}七、常见问题与解决方案
常见问题
动画结束后元素回到初始状态怎么办?
animation-fill-mode 默认为 none。解决方案:设置 animation-fill-mode: forwards 保持结束状态。
动画卡顿不流畅怎么办?
动画属性触发了重排(如 width、height、top、left)。解决方案:改用 transform 和 opacity,添加 will-change 属性。
多个动画冲突怎么办?
多个动画修改同一属性导致冲突。解决方案:确保不同动画修改不同属性,或使用 transform 的组合函数。
如何创建加载动画?
常见的加载动画有旋转圈(border-top-color + spin动画)、弹跳点(scale + delay)、滑动条(translateX),都使用 @keyframes 定义动画,配合 animation 属性控制播放。
如何实现打字机效果?
结合 width 动画和 steps() 时序函数,配合闪烁光标动画:animation: typewriter 3s steps(20) forwards, blink 0.7s step-end infinite。
八、总结
CSS animation 配合 @keyframes 是创建复杂动画的强大工具,通过 name、duration、timing-function、delay、iteration-count、direction、fill-mode、play-state 八个子属性精确控制动画行为。在实际开发中,应优先使用 transform 和 opacity 保证性能,使用 fill-mode: forwards 保持结束状态,尊重 prefers-reduced-motion 用户偏好。
核心原则
优先GPU加速、合理时长、尊重用户偏好、语义化命名。好的CSS动画能提升用户体验,但过度使用会造成视觉疲劳和性能问题。
本文涉及AI创作
内容由AI创作,请仔细甄别