Skip to content

C53. CSS 动画

3.1. ⭐ CSS 动画基础

动画是现代 UI 的重要特征,也是 CSS 突破“静态”的局限,开发动态的无限潜能的重要一步。

3.1.1 @keyframes定义动画序列

通过 @keyframes 规则定义动画的关键帧,控制元素在不同时间点的样式变化。

核心特点

  • 动画名称唯一(如 blink
  • 0%~100%from/to 定义动画过程
  • 可添加中间状态(如 50%
css
/* 闪烁动画示例 */
@keyframes blink {
  0%, 100% { opacity: 1; }
  50% { opacity: 0; }
}

.blink-element {
  animation: blink 1s infinite;
}
html
<div class="blink-element">闪烁文字</div>

3.1.2 动画属性

核心属性速查表

属性名称作用快速记忆口诀
animation-duration动画持续时间时长(如2s
animation-delay动画延迟启动时间等等再开始(如0.5s
animation-fill-mode结束后样式保留记住最后的样子(forwards
animation-iteration-count动画重复次数无限循环(infinite

以上内容全部可以“塞进”animation 属性中作为简写,顺序只需注意第一个时间值作为 <animation-duration>,而第二个时间值(如果存在)作为 <animation-delay>

INFO

因篇幅有限,不引入过多的属性名称。可参考:https://developer.mozilla.org/zh-CN/docs/Web/CSS/CSS_animations/Using_CSS_animations

3.1.3 常见问题

动画不执行?三步排查法:

  1. 是否写了animation-duration
  2. @keyframes名称和animation-name是否一致?
  3. 元素是否被其他样式覆盖?

3.2. 🌟 CSS 动画实现示例

CSS 动画实现有许多技巧、“定式”。先阅读这些基本的代码,然后从中学习 CSS 动画的基本用法,创造自己的动画。

3.2.1 旋转+缩放动画

css
@keyframes spinScale {
  0% { transform: rotate(0deg) scale(1); }
  50% { transform: rotate(180deg) scale(1.2); }
  100% { transform: rotate(360deg) scale(1); }
}

.spinner {
  width: 100px;
  height: 100px;
  margin: 100px;
  background: #4CAF50;
  animation: spinScale 2s infinite ease-in-out;
}
html
<div class="spinner"></div>

3.2.2 按钮悬停动画

css
.button {
  padding: 12px 24px;
  background: #2196F3;
  transition: all 0.3s ease;
}

.button:hover {
  animation: pulse 0.5s ease-in-out;
}

@keyframes pulse {
  0% { transform: scale(1); }
  50% { transform: scale(1.1); }
  100% { transform: scale(1); }
}
html
<button class="button">点击我</button>

3.2.3 无限加载动画

css
.loader {
  border: 4px solid #f3f3f3;
  border-top: 4px solid #3498DB;
  border-radius: 50%;
  width: 40px;
  height: 40px;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
html
<div class="loader"></div>

3.3 (拓展)gasp.js 动画集成

CSS 动画毕竟具有局限性和较高的兼容性要求。真正的“动态语言”——JavaScript,提供了更丰富的动画功能。

GSAP 轮播图实战

html
<div class="carousel">
  <div class="slide" style="background: url(img1.jpg)">Slide 1</div>
  <div class="slide" style="background: url(img2.jpg)">Slide 2</div>
  <div class="slide" style="background: url(img3.jpg)">Slide 3</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.7/dist/gsap.min.js"></script>

<script>
const slides = document.querySelectorAll('.slide');
let currentIndex = 0;

function nextSlide() {
  gsap.to(slides[currentIndex], { duration: 0.5, x: '-100%' });
  currentIndex = (currentIndex + 1) % slides.length;
  gsap.fromTo(slides[currentIndex], { x: '100%' }, { duration: 0.5, x: '0%' });
}

setInterval(nextSlide, 3000);
</script>

知识回顾

  1. @keyframes 动画序列

    • 通过@keyframes定义动画关键帧,控制样式在时间轴上的变化
    • 关键帧名称需唯一,用0%~100%from/to定义动画过程
    • 可添加中间状态(如50%)实现复杂动画效果
  2. 核心动画属性

    属性名称作用快速记忆
    animation-duration动画持续时间必须设置,否则不执行
    animation-delay延迟启动时间默认0
    animation-fill-mode结束后样式保留forwards保持最终状态
    animation-iteration-count重复次数infinite无限循环
  3. 动画执行三要素

    css
    .element {
      animation: 名称 持续时间 速度曲线 延迟 次数 填充模式;
    }
    • 简写时必须包含animation-durationanimation-delay可选
  4. 性能优化技巧

    • 优先使用transformopacity属性实现动画(GPU加速)
    • 避免在动画中触发重排的属性(如width/height
    • 使用will-change提示浏览器提前优化
  5. 常见问题排查

    • 动画未执行?检查:
      1. 是否设置animation-duration
      2. @keyframes名称与animation-name是否一致
      3. 是否被display: none等样式覆盖

课后练习

  1. 补全 @keyframes 动画定义:

    css
    .slide-element {
      animation: slideIn 1s ease-out forwards;
    }
  2. 补全消失动画的 @keyframes 规则:

    css
    .fade {
      animation: fadeOut 1s forwards;
    }
  3. 设计一个「文字打字机」效果:

    • 逐字显示文字
    • 使用@keyframes
    • 添加打字机光标闪烁
参考答案
  1. 参考:

    css
    @keyframes slideIn {
      0% { transform: translateX(-100%); }
      100% { transform: translateX(0); }
    }
  2. 参考:

    css
    @keyframes fadeOut {
      0% { opacity: 1; }
      100% { opacity: 0; }
    }
  3. 文字打字机效果实现:

    css
    /* 打字机效果核心样式 */
    @keyframes typing {
      0% { width: 0; }
      100% { width: 100%; }
    }
    
    @keyframes blink {
      0% { opacity: 0; }
      50% { opacity: 1; }
      100% { opacity: 0; }
    }
    
    .typewriter {
      white-space: nowrap;
      overflow: hidden;
      border-right: 2px solid #000;
      width: fit-content;
      animation:
        typing 2s steps(20, end),
        blink 0.5s infinite;
    }
    
    /* 光标闪烁优化 */
    .typewriter::after {
      content: '';
      animation: blink 0.7s infinite;
    }
    html
    <div class="typewriter">Hello World!</div>

Built by Vitepress | Apache 2.0 Licensed