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: 同时应用 forwardsbackwards 的规则。
  • 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. 最佳实践与注意事项

  • 性能优先,多用 transformopacity:

    • 动画 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 属性。这种方式更符合“关注点分离”的原则,代码也更易于维护。

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;
  }
}

如何测试:

  1. 将上述代码分别保存到 index.htmlstyle.css 文件中。
  2. 在浏览器中打开 index.html
  3. 您将看到:
    • 一个从左侧滑入并停在最终位置的蓝色方块。
    • 一个延迟 0.5 秒后淡入并放大的蓝色方块。
    • 一个无限循环、交替缩放的红色方块(脉冲效果)。
    • 一个不停旋转的加载指示器。
    • 一个不断弹跳的绿色圆形,当您将鼠标悬停在它上面时,动画会暂停。
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐