CSS 动画

目录

一、核心概念与语法

[1. @keyframes 关键帧](#1. @keyframes 关键帧)

[2. animation 属性](#2. animation 属性)

二、动画调速函数(animation-timing-function)

[1. 预设值](#1. 预设值)

[2. 贝塞尔曲线](#2. 贝塞尔曲线)

[3. 步进函数(steps())](#3. 步进函数(steps()))

三、动画控制与交互

[1. 暂停与恢复](#1. 暂停与恢复)

[2. JavaScript 控制](#2. JavaScript 控制)

3.逐帧动画与精灵图

四、性能优化

五、实际应用示例

[1. 淡入淡出效果](#1. 淡入淡出效果)

[2. 旋转加载图标](#2. 旋转加载图标)

[3. 弹跳效果](#3. 弹跳效果)

六、兼容性与前缀

示例:走马灯

示例:全民出游季


CSS 动画允许通过定义关键帧(@keyframes)和动画属性(animation)实现复杂的动态效果,相比 transition 更灵活,支持多阶段控制和循环播放。


一、核心概念与语法

在 CSS 中,以 @ 开头的语法称为 At-Rules(规则声明),用于定义 CSS 的元数据、条件逻辑、外部资源引入等高级功能。

1. @keyframes 关键帧

  • 作用:定义动画的中间状态。

  • 语法

    css 复制代码
    @keyframes 动画名称 {
      from { /* 初始状态 */ }
      to { /* 结束状态 */ }
      /* 或使用百分比 */
      0% { ... }
      50% { ... }
      100% { ... }
    }
  • 示例

    css 复制代码
    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }
    
    @keyframes slideAndRotate {
      0% { transform: translateX(0) rotate(0); }
      50% { transform: translateX(200px) rotate(180deg); }
      100% { transform: translateX(0) rotate(360deg); }
    }

2. animation 属性

  • 作用:将关键帧动画应用到元素。

  • 子属性

    属性 作用 常用值
    animation-name 指定关键帧名称 fadeIn, slideAndRotate
    animation-duration 动画持续时间 2s, 500ms
    animation-timing-function 速度曲线 ease(默认), linear, ease-in-out, cubic-bezier(0.4, 0, 0.2, 1)
    animation-delay 动画延迟时间 1s, 0.5s
    animation-iteration-count 播放次数 1(默认), infinite, 3
    animation-direction 播放方向 normal(默认正向), reverse(反向), alternate(正反交替)
    animation-fill-mode 动画结束后的样式保留 none(默认), forwards(保持最后一帧), backwards(应用第一帧)
    animation-play-state 控制播放状态 running(默认), paused(暂停)
  • 简写语法

    css 复制代码
    .element {
      animation: name duration timing-function delay iteration-count direction fill-mode play-state;
    }

    示例

    css 复制代码
    .box {
      animation: fadeIn 2s ease-in-out 1s infinite alternate forwards;
    }

二、动画调速函数(animation-timing-function

1. 预设值

  • ease:默认缓入缓出(先加速后减速)。

  • linear:匀速。

  • ease-in:缓入(逐渐加速)。

  • ease-out:缓出(逐渐减速)。

  • ease-in-out:缓入缓出。

2. 贝塞尔曲线

  • 使用 cubic-bezier(x1, y1, x2, y2) 自定义速度曲线。
css 复制代码
.box {
  animation-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
}

3. 步进函数(steps()

  • 将动画拆分为固定步数播放,适合帧动画。

    css 复制代码
    .box {
      animation-timing-function: steps(5, jump-start); /* 分 5 步跳跃播放 */
    }

三、动画控制与交互

1. 暂停与恢复

  • 通过 animation-play-state 控制:

    css 复制代码
    .box:hover {
      animation-play-state: paused; /* 悬停时暂停动画 */
    }

2. JavaScript 控制

  • 动态添加/移除动画类:

    css 复制代码
    const box = document.querySelector('.box');
    box.classList.add('fadeIn');  // 触发动画
    box.style.animation = 'none'; // 停止动画

3.逐帧动画与精灵图

css 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
    <link rel="stylesheet" href="./iconfont/iconfont.css">
    <style>

        .box {
            margin: 100px auto;
            width: 1000px;
        }

        .people {
            width: 140px;
            height: 140px;
            background-image: url(./res/run.png);

            animation: 
                run 1s steps(12) infinite,
                move 4s linear infinite;
        }

        @keyframes run {
            from {
                background-position: 0 0;
            }
            
            to {
                background-position: -1680px 0;
            }
        }

        @keyframes move {
            0% {
                transform: translate(0) scaleX(1);
            }
            
            50% {
                transform: translate(800px) scaleX(1);
            }

            50.1% {
                transform: translate(800px) scaleX(-1);
            }

            100% {
                transform: translate(0) scaleX(-1);
            }

        }

    </style>
</head>
<body>
    <div class="box">
        <div class="people"></div>
    </div>

</body>
</html>

四、性能优化

  1. 优先使用 transformopacity

    • 这些属性由 GPU 加速,避免触发重排(如 widthmargin)。
  2. 减少动画数量

    • 同时运行过多动画可能导致页面卡顿。
  3. 使用 will-change 提示浏览器

    css 复制代码
    .box {
      will-change: transform, opacity; /* 提前告知浏览器可能变化的属性 */
    }

五、实际应用示例

1. 淡入淡出效果

css 复制代码
@keyframes fadeInOut {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}

.element {
  animation: fadeInOut 3s ease-in-out infinite;
}

2. 旋转加载图标

css 复制代码
@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.loader {
  animation: spin 1s linear infinite;
}

3. 弹跳效果

css 复制代码
@keyframes bounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-30px); }
}

.button {
  animation: bounce 1s ease-in-out infinite;
}

六、兼容性与前缀

  • 现代浏览器:无需前缀(Chrome 43+、Firefox 16+、Safari 9+)。

  • 旧版浏览器 :需添加 -webkit- 前缀:

    css 复制代码
    @-webkit-keyframes fadeIn { ... }
    .box {
      -webkit-animation: fadeIn 2s;
    }

示例:走马灯

css 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
    <link rel="stylesheet" href="./iconfont/iconfont.css">
    <style>

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        li {
            list-style: none;
        }

        a {
            text-decoration: none;
            color: #fff;
        }

        .box {
            margin: 100px auto;

            width: 300px;
            height: 50px;
            overflow: hidden;
        }

        .box ul {
            display: flex;
            animation: move 7s linear infinite;
        }

        .box:hover ul {
            animation-play-state: paused;
        }

        @keyframes move {
            from {
                transform: translateX(0);
            }
            to {
                transform: translateX(-700px);
            }
        }

        .box img {
            width: 100px;
        }

    </style>
</head>
<body>
    <div class="box">
        <ul>
            <li><img src="./res/1.jpg" alt=""></li>
            <li><img src="./res/2.jpg" alt=""></li>
            <li><img src="./res/3.jpg" alt=""></li>
            <li><img src="./res/4.jpg" alt=""></li>
            <li><img src="./res/5.jpg" alt=""></li>
            <li><img src="./res/6.jpg" alt=""></li>
            <li><img src="./res/7.jpg" alt=""></li>
            <!-- 填补显示区域的空白 -->
            <li><img src="./res/1.jpg" alt=""></li>
            <li><img src="./res/2.jpg" alt=""></li>
            <li><img src="./res/3.jpg" alt=""></li>
        </ul>
    </div>

</body>
</html>

示例:全民出游季

css 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
    <link rel="stylesheet" href="./iconfont/iconfont.css">
    <style>

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        li {
            list-style: none;
        }

        a {
            text-decoration: none;
            color: #fff;
        }

        html {
            height: 100%;   
        }

        body {
            height: 100%;
            background: url(./res/images/f1_1.jpg) no-repeat center 0 / cover;   
        }

        .cover {
            width: 100%;
            height: 100%;   
            position: relative;
        }

        .cover div {
            position: absolute;
        }

        .title {
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
            animation: show 1s;
        }

        @keyframes show {
            0% {
                transform: translate(-50%,-50%) scale(1);
            }
            20% {
                transform: translate(-50%,-50%) scale(0.3);
            }
            50% {
                transform: translate(-50%,-50%) scale(1.7);
            }
            80% {
                transform: translate(-50%,-50%) scale(0.8);
            }
            100% {
                transform: translate(-50%,-50%) scale(1);
            }
        }

        .label {
            bottom: 10%;
            left: 50%;
            transform: translate(-50%);
        }

        .label ul {
            display: flex;
            justify-content: space-between;
        }

        .label ul img {
            width: 100px;
            margin: 0 85px;
            animation: bounce .8s ease-in infinite alternate;
        }

        .label ul li:nth-child(2) img {
            animation: bounce .8s 0.3s ease-in infinite alternate;
        }

        .label ul li:nth-child(3) img {
            animation: bounce .8s 0.6s ease-in infinite alternate;
        }

        .label ul li:nth-child(4) img {
            animation: bounce .8s 0.9s ease-in infinite alternate;
        }

        @keyframes bounce {
            from {
                transform: translateY(0);
            }

            to {
                transform: translateY(30px);
            }
        }
        
        .cloud {
            position: relative;
            left: 50%;
        }

        .cloud img:nth-child(1) {
            top: 20px;
            margin-left: -200px;
        }

        .cloud img:nth-child(2) {
            top: 100px;
            margin-left: 400px;
        }

        .cloud img:nth-child(3) {
            top: 180px;
            margin-left: -500px;
        }

        .cloud img {
            position: absolute;
            animation: move 2s linear infinite alternate;
        }

        @keyframes move {
            to {
                transform: translate(-50px);
            }
        }

        .lu {
            top: 15%;
            left: 60%;
        }
        
        .san {
            top: 15%;
            left: 25%;
            animation: float 1.5s linear infinite alternate;
        }

        @keyframes float {
            to {
                transform: translateY(50px);
            }
        }

    </style>
</head>
<body>
    <div class="cover">
        <div class="cloud">
            <img src="./res/images/yun1.png" alt="">
            <img src="./res/images/yun2.png" alt="">
            <img src="./res/images/yun3.png" alt="">
        </div>    
        <div class="lu"><img src="./res/images/lu.png" alt=""></div>    
        <div class="san"><img src="./res/images/san.png" alt=""></div>
        <div class="label">
            <ul>
                <li><img src="./res/images/1.png" alt=""></li>
                <li><img src="./res/images/2.png" alt=""></li>
                <li><img src="./res/images/3.png" alt=""></li>
                <li><img src="./res/images/4.png" alt=""></li>
            </ul>
        </div>
        <div class="title"><img src="./res/images/font1.png" alt=""></div>

    </div>

</body>
</html>
相关推荐
恋猫de小郭4 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅11 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606111 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了11 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅11 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅12 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅12 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment12 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅13 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊13 小时前
jwt介绍
前端