深入解析 CSS `animation` 属性
·
CSS animation 属性允许开发者通过定义一系列的关键帧(keyframes)来创建复杂的动画序列。与只能定义“开始”和“结束”两个状态的 transition 不同,animation 能够控制动画过程中的多个中间状态,实现更丰富、更具表现力的动态效果。
1. CSS 动画的核心组成
一个完整的 CSS 动画由两个核心部分构成,二者缺一不可:
@keyframes规则: 这是动画的“剧本”或“时间轴”。你可以在@keyframes规则中定义动画在不同时间点的状态。通过设置从0%(from) 到100%(to) 的多个百分比节点,你可以精确描述元素在动画周期中各个阶段的样式(例如位置、颜色、大小等)。animation相关属性: 这些属性被应用在目标元素上,用于“调用”并“配置”上面定义好的@keyframes剧本。它们决定了动画的名称、持续时间、速度曲线、循环次数等具体播放细节。
2. animation 的各个子属性 (Longhand Properties)
虽然我们通常使用 animation 简写属性,但理解其每一个子属性(longhand properties)是精通 CSS 动画的关键。
-
animation-name- 作用: 指定要绑定的
@keyframes规则的名称。这个名称必须与@keyframes后面定义的标识符完全匹配。 - 语法:
animation-name: none | <keyframes-name>; - 示例:
animation-name: slide-in;
- 作用: 指定要绑定的
-
animation-duration- 作用: (必需) 定义动画完成一个周期所需要的时间。单位为秒 (
s) 或毫秒 (ms)。 - 语法:
animation-duration: <time>; - 示例:
animation-duration: 2s;
- 作用: (必需) 定义动画完成一个周期所需要的时间。单位为秒 (
-
animation-timing-function- 作用: 定义动画在每个周期内的速度曲线(加速度)。
- 语法:
animation-timing-function: <easing-function>; - 常见值:
linear: 匀速。ease: (默认值)慢速开始,然后加速,最后慢速结束。ease-in: 慢速开始。ease-out: 慢速结束。ease-in-out: 慢速开始和结束。cubic-bezier(n,n,n,n): 自定义贝塞尔曲线。steps(n, <jumpterm>): 定义阶跃动画,将动画分为 n 个步骤执行。
-
animation-delay- 作用: 定义在动画开始前等待的时间。
- 语法:
animation-delay: <time>; - 示例:
animation-delay: 0.5s;(等待 0.5 秒后开始)
-
animation-iteration-count- 作用: 定义动画播放的次数。
- 语法:
animation-iteration-count: <number> | infinite; - 示例:
animation-iteration-count: 3;(播放 3 次),animation-iteration-count: infinite;(无限循环)。
-
animation-direction- 作用: 定义动画在一个周期结束后是否反向播放。
- 语法:
animation-direction: normal | reverse | alternate | alternate-reverse; - 值解释:
normal: (默认值)每个周期都正向播放。reverse: 每个周期都反向播放。alternate: 奇数次正向播放,偶数次反向播放。alternate-reverse: 奇数次反向播放,偶数次正向播放。
-
animation-fill-mode- 作用: 定义动画在执行之前和结束之后的样式状态。这是一个非常重要的属性。
- 语法:
animation-fill-mode: none | forwards | backwards | both; - 值解释:
none: (默认值)动画执行前后,元素的样式将恢复为原始状态。forwards: 动画结束后,元素将保持动画最后一帧(100%)的样式。backwards: 动画开始前(在delay期间),元素将应用动画第一帧(0%)的样式。both: 同时应用forwards和backwards的规则。
-
animation-play-state- 作用: 控制动画的运行状态(播放或暂停)。
- 语法:
animation-play-state: running | paused; - 说明: 这个属性通常与 JavaScript 或
:hover等伪类配合,用于实现交互式的动画控制。
3. animation 简写语法 (Shorthand Syntax)
在实际开发中,我们通常使用 animation 简写属性来一次性设置所有子属性。
- 语法:
animation: <name> <duration> <timing-function> <delay> <iteration-count> <direction> <fill-mode> <play-state>; - 注意:
- 其中
<duration>是必需的(如果省略了<name>,则动画无效)。 - 值的顺序可以不完全固定,但涉及时间的两个值
<duration>和<delay>,第一个被解析为duration,第二个为delay。 - 可以同时定义多个动画,用逗号
,分隔。
- 其中
4. 浏览器兼容性 (Browser Compatibility)
animation 相关属性在所有现代浏览器中都有非常好的支持。不过,为了兼容一些旧版本的浏览器(特别是基于 WebKit 内核的),建议同时提供 -webkit- 前缀。
.box {
-webkit-animation: slide-in 1s; /* 兼容旧版 WebKit 浏览器 */
animation: slide-in 1s;
}
@-webkit-keyframes slide-in { /* 对应的 keyframes 也要加前缀 */
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
@keyframes slide-in {
from { transform: translateX(-100%); }
to { transform: translateX(0); }
}
5. 最佳实践与注意事项
-
性能优先,多用
transform和opacity:- 动画
transform(移动、缩放、旋转) 和opacity(不透明度) 属性性能最高。因为浏览器可以将它们的计算委托给 GPU,不引起页面的重排 (reflow) 和重绘 (repaint)。 - 应尽量避免对
width,height,left,top等会影响页面布局的属性进行动画,因为它们会消耗更多的 CPU 资源,可能导致动画卡顿。
- 动画
-
考虑可访问性 (Accessibility):
- 不是所有用户都喜欢动画。对于有前庭功能障碍的用户,过多的动效可能引起眩晕。
- 使用
prefers-reduced-motion媒体查询来尊重用户的系统偏好。当用户希望减少动效时,应禁用或减弱动画。
@media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; } } -
用类名 (Class) 控制动画:
- 在 JavaScript 中,推荐通过添加或移除 CSS 类名来触发或停止动画,而不是直接修改
animation属性。这种方式更符合“关注点分离”的原则,代码也更易于维护。
- 在 JavaScript 中,推荐通过添加或移除 CSS 类名来触发或停止动画,而不是直接修改
6. 完整示例 (Complete Example)
下面是一个综合示例,展示了多种动画效果以及交互式控制。
HTML (index.html):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS animation 属性示例 v2.0</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>CSS `animation` 属性演示</h1>
</header>
<main>
<div class="example-section">
<h2>基本动画效果</h2>
<div class="box slide">从左侧滑入并保持</div>
<div class="box fade">淡入并放大</div>
</div>
<div class="example-section">
<h2>循环与方向</h2>
<div class="box pulse">无限脉冲效果 (alternate)</div>
<div class="spinner"></div>
</div>
<div class="example-section">
<h2>交互式控制 (鼠标悬停暂停)</h2>
<div class="box interactive-bounce"></div>
</div>
</main>
</body>
</html>
CSS (style.css):
/* 全局与布局样式 */
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
background-color: #f0f2f5;
color: #333;
line-height: 1.6;
}
header {
background-color: #6f42c1;
color: #fff;
padding: 20px;
text-align: center;
margin-bottom: 30px;
}
main {
max-width: 800px;
margin: 0 auto;
padding: 0 20px;
}
.example-section {
background-color: #fff;
border: 1px solid #ddd;
padding: 20px;
margin-bottom: 25px;
border-radius: 8px;
min-height: 150px;
}
.example-section h2 {
margin-top: 0;
color: #6f42c1;
border-bottom: 1px dashed #e0e0e0;
padding-bottom: 10px;
}
.box {
width: 150px;
height: 80px;
background-color: #007bff;
color: white;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
border-radius: 8px;
margin: 20px 0;
padding: 10px;
}
/* 1. 定义 @keyframes 动画剧本 */
/* 从左侧滑入 */
@keyframes slide-in {
from {
transform: translateX(-150%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
/* 淡入并放大 */
@keyframes fade-zoom-in {
0% {
opacity: 0;
transform: scale(0.5);
}
100% {
opacity: 1;
transform: scale(1);
}
}
/* 脉冲效果 */
@keyframes pulse {
from {
transform: scale(1);
box-shadow: 0 0 0 0 rgba(220, 53, 69, 0.7);
}
to {
transform: scale(1.05);
box-shadow: 0 0 0 15px rgba(220, 53, 69, 0);
}
}
/* 旋转加载 */
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
/* 弹跳效果 (多关键帧) */
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
/* 2. 将动画应用到元素上 */
.slide {
/* animation: name duration fill-mode; */
animation: slide-in 1s forwards;
}
.fade {
/* animation: name duration timing-function delay; */
animation: fade-zoom-in 0.8s ease-out 0.5s forwards;
}
.pulse {
background-color: #dc3545;
/* animation: name duration iteration-count direction; */
animation: pulse 1.5s infinite alternate;
}
.spinner {
width: 50px;
height: 50px;
border: 5px solid #f3f3f3;
border-top: 5px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
.interactive-bounce {
width: 60px;
height: 60px;
border-radius: 50%;
background-color: #28a745;
/* animation: name duration timing-function iteration-count play-state; */
animation: bounce 2s ease-in-out infinite running;
}
.interactive-bounce:hover {
/* 鼠标悬停时暂停动画 */
animation-play-state: paused;
}
/* 3. 尊重用户对动效的偏好 */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
}
}
如何测试:
- 将上述代码分别保存到
index.html和style.css文件中。 - 在浏览器中打开
index.html。 - 您将看到:
- 一个从左侧滑入并停在最终位置的蓝色方块。
- 一个延迟 0.5 秒后淡入并放大的蓝色方块。
- 一个无限循环、交替缩放的红色方块(脉冲效果)。
- 一个不停旋转的加载指示器。
- 一个不断弹跳的绿色圆形,当您将鼠标悬停在它上面时,动画会暂停。
更多推荐




所有评论(0)