CSS3 animation-fill-mode 属性详解

核心知识点

animation-fill-mode 属性概述

animation-fill-mode 是 CSS3 中的一个动画属性,用于指定动画在播放前后如何应用样式。它允许开发者控制元素在动画开始前和结束后的状态,而不仅仅是在动画播放期间。

animation-fill-mode 属性语法

animation-fill-mode: none | forwards | backwards | both;

animation-fill-mode 属性取值

描述
none 默认值,动画结束后元素回到初始状态,不保留动画结束时的样式
forwards 动画结束后,元素保持动画结束时的样式
backwards 动画开始前,元素应用动画开始时的样式(在延迟期间也会应用)
both 同时应用 forwardsbackwards 的效果,即动画开始前应用开始样式,结束后保持结束样式

实用案例分析

基本使用示例

示例 1:不同填充模式的效果对比

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS3 animation-fill-mode 基本示例</title>
    <style>
        /* 定义关键帧 */
        @keyframes slide {
            from {
                transform: translateX(0);
                background-color: #3498db;
            }
            to {
                transform: translateX(200px);
                background-color: #e74c3c;
            }
        }
        
        /* 应用动画 */
        .box {
            width: 100px;
            height: 100px;
            margin: 50px 20px;
            display: inline-block;
            animation-name: slide;
            animation-duration: 2s;
            animation-timing-function: ease-in-out;
            animation-delay: 1s;
        }
        
        /* 默认值 none */
        .box1 {
            animation-fill-mode: none;
        }
        
        /* forwards */
        .box2 {
            animation-fill-mode: forwards;
        }
        
        /* backwards */
        .box3 {
            animation-fill-mode: backwards;
        }
        
        /* both */
        .box4 {
            animation-fill-mode: both;
        }
    </style>
</head>
<body>
    <div class="box box1">none</div>
    <div class="box box2">forwards</div>
    <div class="box box3">backwards</div>
    <div class="box box4">both</div>
    <p>注意观察:</p>
    <ul>
        <li>动画开始前(延迟期间)各元素的状态</li>
        <li>动画结束后各元素的状态</li>
    </ul>
</body>
</html>

效果说明

  • 定义了一个名为 slide 的关键帧动画,实现元素从左向右滑动并改变背景颜色的效果
  • 为四个 .box 元素应用了相同的动画,但设置了不同的 animation-fill-mode
  • 可以观察到:
    • none:动画开始前保持初始状态,动画结束后回到初始状态
    • forwards:动画开始前保持初始状态,动画结束后保持结束状态
    • backwards:动画开始前(延迟期间)就应用开始状态的样式,动画结束后回到初始状态
    • both:动画开始前应用开始状态的样式,动画结束后保持结束状态

示例 2:结合延迟的效果

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS3 animation-fill-mode 结合延迟示例</title>
    <style>
        /* 定义关键帧 */
        @keyframes fadeIn {
            from {
                opacity: 0;
                transform: translateY(20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        
        /* 应用动画 */
        .box {
            width: 200px;
            height: 100px;
            margin: 50px 20px;
            display: inline-block;
            background-color: #3498db;
            color: white;
            text-align: center;
            line-height: 100px;
            animation-name: fadeIn;
            animation-duration: 1s;
            animation-timing-function: ease-out;
            animation-delay: 2s;
        }
        
        /* 无填充模式 */
        .box1 {
            animation-fill-mode: none;
        }
        
        /* 向后填充 */
        .box2 {
            animation-fill-mode: backwards;
        }
    </style>
</head>
<body>
    <div class="box box1">none</div>
    <div class="box box2">backwards</div>
    <p>注意观察:在动画开始前的 2 秒延迟期间,两个元素的状态差异。</p>
</body>
</html>

效果说明

  • 定义了一个名为 fadeIn 的关键帧动画,实现元素的淡入和上移效果
  • 为两个 .box 元素应用了相同的动画,但设置了不同的 animation-fill-mode
  • 可以观察到:
    • none:在 2 秒延迟期间,元素保持初始状态(可见且位置正常)
    • backwards:在 2 秒延迟期间,元素就应用了开始状态的样式(透明且向下偏移)

实际应用场景

场景 1:页面元素入场动画

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS3 页面元素入场动画</title>
    <style>
        /* 定义入场动画关键帧 */
        @keyframes slideInFromLeft {
            from {
                transform: translateX(-100%);
                opacity: 0;
            }
            to {
                transform: translateX(0);
                opacity: 1;
            }
        }
        
        /* 标题样式 */
        .title {
            font-size: 36px;
            font-weight: bold;
            margin: 50px;
            animation-name: slideInFromLeft;
            animation-duration: 1s;
            animation-timing-function: ease-out;
            animation-fill-mode: both;
        }
        
        /* 内容样式 */
        .content {
            font-size: 18px;
            margin: 50px;
            line-height: 1.5;
            animation-name: slideInFromLeft;
            animation-duration: 1s;
            animation-timing-function: ease-out;
            animation-delay: 0.3s;
            animation-fill-mode: both;
        }
        
        /* 按钮样式 */
        .btn {
            padding: 10px 20px;
            background-color: #3498db;
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 16px;
            cursor: pointer;
            margin: 50px;
            animation-name: slideInFromLeft;
            animation-duration: 1s;
            animation-timing-function: ease-out;
            animation-delay: 0.6s;
            animation-fill-mode: both;
        }
    </style>
</head>
<body>
    <h1 class="title">欢迎访问我们的网站</h1>
    <p class="content">这是一个使用 CSS3 动画实现的页面元素入场效果示例。通过设置不同的动画延迟和 fill-mode: both,我们可以创建出元素依次从左侧滑入的效果,并且在动画结束后保持元素的最终状态。</p>
    <button class="btn">了解更多</button>
</body>
</html>

效果说明

  • 定义了一个名为 slideInFromLeft 的关键帧动画,实现元素从左侧滑入并淡入的效果
  • 为页面标题、内容和按钮应用了相同的动画,但设置了不同的延迟时间
  • 使用 animation-fill-mode: both 确保元素在动画开始前(延迟期间)保持透明且在左侧,动画结束后保持最终位置和透明度
  • 通过设置递增的延迟时间,实现了元素依次入场的效果

场景 2:悬停效果

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS3 悬停效果</title>
    <style>
        /* 定义悬停动画关键帧 */
        @keyframes hoverEffect {
            from {
                transform: scale(1);
                box-shadow: 0 0 0 rgba(52, 152, 219, 0);
            }
            to {
                transform: scale(1.05);
                box-shadow: 0 5px 15px rgba(52, 152, 219, 0.3);
            }
        }
        
        /* 按钮样式 */
        .btn {
            padding: 15px 30px;
            background-color: #3498db;
            color: white;
            border: none;
            border-radius: 5px;
            font-size: 18px;
            font-weight: bold;
            cursor: pointer;
            margin: 100px 20px;
            display: inline-block;
            transition: background-color 0.3s ease;
        }
        
        /* 应用动画 */
        .btn.animated {
            animation-name: hoverEffect;
            animation-duration: 0.3s;
            animation-timing-function: ease-out;
            animation-fill-mode: forwards;
        }
        
        /* 按钮悬停 */
        .btn:hover {
            background-color: #2980b9;
        }
        
        /* 触发动画 */
        .btn.animated:hover {
            animation-play-state: running;
        }
        
        /* 重置动画 */
        .btn.animated:not(:hover) {
            animation-name: none;
        }
    </style>
</head>
<body>
    <button class="btn">普通按钮</button>
    <button class="btn animated">动画按钮</button>
    <p>悬停在两个按钮上,观察效果差异。</p>
</body>
</html>

效果说明

  • 定义了一个名为 hoverEffect 的关键帧动画,实现元素的缩放和阴影效果
  • 为第二个按钮应用了动画,并设置 animation-fill-mode: forwards 使其在动画结束后保持放大和有阴影的状态
  • 当鼠标悬停在按钮上时,触发动画;当鼠标移开时,动画重置
  • 可以观察到,使用 animation-fill-mode: forwards 的按钮在悬停时会保持动画结束时的状态,而普通按钮则没有这种效果

场景 3:状态切换动画

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS3 状态切换动画</title>
    <style>
        /* 定义激活动画关键帧 */
        @keyframes activate {
            from {
                background-color: #f0f0f0;
                transform: scale(1);
            }
            to {
                background-color: #2ecc71;
                transform: scale(1.1);
            }
        }
        
        /* 定义停用动画关键帧 */
        @keyframes deactivate {
            from {
                background-color: #2ecc71;
                transform: scale(1.1);
            }
            to {
                background-color: #f0f0f0;
                transform: scale(1);
            }
        }
        
        /* 切换按钮样式 */
        .toggle {
            width: 200px;
            height: 100px;
            margin: 100px auto;
            background-color: #f0f0f0;
            border-radius: 50px;
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 18px;
            font-weight: bold;
            animation-duration: 0.5s;
            animation-timing-function: ease-out;
            animation-fill-mode: forwards;
        }
        
        /* 激活状态 */
        .toggle.active {
            animation-name: activate;
        }
        
        /* 停用状态 */
        .toggle:not(.active) {
            animation-name: deactivate;
        }
    </style>
</head>
<body>
    <div class="toggle" onclick="this.classList.toggle('active')">
        点击切换状态
    </div>
</body>
</html>

效果说明

  • 定义了两个关键帧动画:activate(激活状态)和 deactivate(停用状态)
  • 为切换按钮应用了动画,并设置 animation-fill-mode: forwards 使其在动画结束后保持最终状态
  • 当点击按钮时,切换其 active 类,从而触发不同的动画
  • 可以观察到,按钮在激活和停用时会有平滑的动画过渡,并且在动画结束后保持相应的状态

代码优化建议

  1. 合理选择填充模式

    • 对于一次性的入场动画,建议使用 both,这样元素在动画开始前(延迟期间)会保持初始状态,动画结束后保持结束状态
    • 对于需要保持结束状态的动画,如悬停效果、状态切换等,建议使用 forwards
    • 对于需要在延迟期间就应用开始状态的动画,建议使用 backwardsboth
    • 对于不需要特殊处理的动画,使用默认值 none 即可
  2. 结合其他动画属性

    • animation-delay 结合使用 backwardsboth,可以在延迟期间就显示动画的开始状态
    • animation-iteration-count: infinite 结合使用时,fill-mode 可能不会有明显效果,因为动画会无限循环
    • animation-direction: alternate 结合使用时,需要注意 forwards 会保持最后一次动画结束时的状态
  3. 性能考虑

    • 对于复杂的动画,建议使用 transformopacity 属性,因为它们可以利用 GPU 加速
    • 避免在动画中使用会触发重排的属性,如 widthheighttopleft
    • 对于需要频繁触发的动画,如悬停效果,建议使用 transition 而不是 animation,因为 transition 更加轻量
  4. 用户体验

    • 对于页面加载时的元素入场动画,使用 both 可以确保元素在动画开始前不会突然出现
    • 对于需要用户交互的元素,如按钮、链接等,使用 forwards 可以在动画结束后保持高亮状态
    • 避免使用过于复杂的动画,这可能会分散用户的注意力或导致视觉疲劳
  5. 兼容性处理

    • 虽然现代浏览器已经广泛支持 CSS3 动画,但为了兼容旧版浏览器,可以添加浏览器前缀
    • 例如:-webkit-animation-fill-mode-moz-animation-fill-mode-o-animation-fill-mode

总结

animation-fill-mode 属性是 CSS3 动画系统中的一个重要组成部分,它用于控制动画在播放前后如何应用样式。通过合理设置 animation-fill-mode 属性的值,开发者可以创建出更加自然和流畅的动画效果,而不仅仅是在动画播放期间。

在实际开发中,建议根据具体的动画需求和场景选择合适的填充模式,并结合其他动画属性(如 animation-delayanimation-direction 等),创建出符合用户体验的动画效果。同时,要注意性能优化,避免过多的复杂动画导致页面性能下降。

至此,我们已经完成了 CSS3 动画属性的系列教程,包括:

  • animation(复合属性)
  • animation-name(动画名称)
  • animation-duration(动画持续时间)
  • animation-timing-function(动画时间函数)
  • animation-delay(动画延迟)
  • animation-iteration-count(动画重复次数)
  • animation-direction(动画方向)
  • animation-fill-mode(动画填充模式)

通过掌握这些动画属性,开发者可以创建出各种丰富多样的动画效果,提升网页的视觉体验和用户交互。

« 上一篇 CSS3 animation-direction 属性详解 下一篇 » CSS3 动画与变换 - animation-play-state 属性