CSS动画实战锦囊,让网页“动”起来

33 阅读9分钟

各位大佬们,我整理了几个CSS动画实用案例,对刚接触CSS的新手或者经常做动画的大佬们,也许会是个不错的收藏哦。

1. 导航下划线悬停动画

场景:导航菜单、标签页切换的视觉反馈。

技巧:使用伪元素配合 transform: scaleX() 实现从中间向两端延伸的效果。

为什么实用:给用户明确的视觉反馈,知道当前正在浏览哪个导航项,提升交互感。

html

<nav>
  <a href="#">首页</a>
  <a href="#">产品</a>
  <a href="#">关于</a>
</nav>

css

nav a {
  position: relative;
  text-decoration: none;
  color: #333;
  padding: 8px 0;
  margin: 0 16px;
}

/* 下划线伪元素 */
nav a::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 0;
  height: 2px;
  background: #007bff;
  transition: all 0.3s ease;
  transform: translateX(-50%);
}

nav a:hover::after {
  width: 100%; /* 从中间向两边扩展 */
}

3月6日(1).gif

2. 纯CSS加载动画(旋转圆环)

场景:异步请求加载、页面初始化等待。

技巧:利用 border 属性制作圆环,通过 animation 无限旋转。

为什么实用:轻量、无需图片或JS,任何网页都能快速实现加载反馈。

html

<div class="spinner"></div>

css

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid rgba(0, 123, 255, 0.2);
  border-top-color: #007bff;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

3月6日(2).gif

3. 3D卡片翻转

场景:产品展示、会员卡正反面信息切换。

技巧perspective 开启3D空间,backface-visibility 隐藏背面。

为什么实用:适合做产品展示、卡片式菜单、信息正反面切换,节省空间又酷炫。

html

<div class="card-container">
  <div class="card">
    <div class="card-front">正面内容</div>
    <div class="card-back">背面内容</div>
  </div>
</div>

css

.card-container {
  width: 200px;
  height: 260px;
  perspective: 1000px; /* 3D视距 */
}

.card {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.6s;
}

.card:hover {
  transform: rotateY(180deg);
}

.card-front, .card-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden; /* 隐藏背面 */
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
}

.card-front {
  background: #007bff;
  color: white;
}

.card-back {
  background: #ff5722;
  color: white;
  transform: rotateY(180deg);
}

3月6日(3).gif

4. 脉冲波纹(提醒效果)

场景:消息通知、直播红点、地图定位标记。

技巧box-shadow 配合 scale 和 opacity 动画。

为什么实用:常用于消息通知、直播红点、地图标记,吸引用户注意但不刺眼。

html

<div class="pulse-dot"></div>

css

.pulse-dot {
  width: 20px;
  height: 20px;
  background: #ff4444;
  border-radius: 50%;
  box-shadow: 0 0 0 0 rgba(255, 68, 68, 0.5);
  animation: pulse 1.5s infinite;
}

@keyframes pulse {
  to {
    box-shadow: 0 0 0 15px rgba(255, 68, 68, 0);
    transform: scale(1.2);
  }
}

3月6日(4).gif

5. 滚动渐入效果(结合Intersection Observer)

场景:页面滚动时元素逐渐浮现,增加浏览节奏感。

技巧:JS负责添加类名,CSS控制透明度与位移。
(实际项目中可搭配ScrollReveal库,这里展示原生实现)

为什么实用:增强页面滚动时的层次感,让内容逐一呈现,避免一次性全部展示带来的压迫感。

html

<div class="scroll-item">内容块1</div>
<div class="scroll-item">内容块2</div>

css

.scroll-item {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}

.scroll-item.visible {
  opacity: 1;
  transform: translateY(0);
}

javascript

// 简单的 Intersection Observer
const items = document.querySelectorAll('.scroll-item');
const observer = new IntersectionObserver(entries => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      entry.target.classList.add('visible');
      // 可选:如果只需要触发一次,可以取消观察
      observer.unobserve(entry.target);
    }
  });
}, { threshold: 0.2 });

items.forEach(item => observer.observe(item));

3月6日(5).gif

6. 手风琴折叠菜单(纯CSS)

场景:FAQ列表、侧边栏折叠导航。

技巧:利用 checkbox 和 max-height 实现平滑展开/收起。

为什么实用:纯CSS实现,无需JavaScript,适合做FAQ、折叠面板,节省页面空间。

html

<div class="accordion">
  <input type="checkbox" id="item1" class="accordion-checkbox">
  <label for="item1" class="accordion-label">菜单标题1</label>
  <div class="accordion-content">
    <p>这里是展开后显示的内容,可以放任意HTML元素。</p>
  </div>
</div>

css

.accordion {
  margin-bottom: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.accordion-checkbox {
  display: none; /* 隐藏原生复选框 */
}

.accordion-label {
  display: block;
  padding: 12px;
  background: #f5f5f5;
  cursor: pointer;
  font-weight: bold;
}

.accordion-content {
  max-height: 0;
  overflow: hidden;
  padding: 0 12px;
  background: white;
  transition: max-height 0.3s ease-out, padding 0.2s;
}

/* 复选框选中时改变内容区域高度(需大于实际内容高度) */
.accordion-checkbox:checked + .accordion-label + .accordion-content {
  max-height: 200px; /* 根据内容调整 */
  padding: 12px;
}

3月6日(6).gif

7. 卡片图片悬停缩放

场景:电商商品列表、作品集展示。

技巧overflow: hidden 容器内图片 transform: scale()

为什么实用:电商网站、作品集常用,强调图片可点击或引起用户兴趣。

html

<div class="product-card">
  <div class="product-image">
    <img src="https://via.placeholder.com/300" alt="商品图">
  </div>
  <p>商品名称</p>
</div>

css

.product-card {
  width: 200px;
  text-align: center;
}

.product-image {
  width: 200px;
  height: 200px;
  overflow: hidden; /* 隐藏超出部分 */
  border-radius: 8px;
}

.product-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.4s ease;
}

.product-image:hover img {
  transform: scale(1.1); /* 放大1.1倍 */
}

动画性能小贴士

  • 优先使用 transform 和 opacity:它们不会触发页面重排(reflow),性能最佳。
  • 避免动画高开销属性:如 widthheightleft/top,容易导致卡顿。
  • 考虑用户偏好:尊重 prefers-reduced-motion,对动晕症用户减少动画。

css

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

3月6日(7).gif

以上案例基本覆盖了日常开发中90%的动画需求,您可以根据实际项目调整颜色、时长和缓动函数。如果需要更复杂的交互动画,可以在此基础组合使用。

写到最后

给新手小伙伴们,提供包含所有实战案例的完整HTML文件。您可以直接复制保存为 .html 文件并在浏览器中打开查看效果。每个案例独立作用域,样式互不干扰。

html

<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS动画实战案例合集</title>
  <style>
    /* 页面基础样式,仅用于布局展示,不影响动画案例本身 */
    body {
      font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
      background: #f7f9fc;
      margin: 0;
      padding: 20px;
      color: #1e293b;
    }
    .container {
      max-width: 1200px;
      margin: 0 auto;
      display: flex;
      flex-direction: column;
      gap: 40px;
    }
    .demo-section {
      background: white;
      border-radius: 20px;
      padding: 24px;
      box-shadow: 0 10px 25px -5px rgba(0,0,0,0.05);
    }
    .demo-section h2 {
      margin-top: 0;
      margin-bottom: 24px;
      font-weight: 600;
      font-size: 1.5rem;
      border-left: 5px solid #3b82f6;
      padding-left: 16px;
    }
    .demo-box {
      display: flex;
      flex-wrap: wrap;
      gap: 30px;
      align-items: center;
      justify-content: center;
      min-height: 180px;
    }
    hr {
      border: none;
      border-top: 2px dashed #cbd5e1;
      margin: 40px 0 20px;
    }
    /* 性能小贴士:尊重用户减少动画偏好 */
    @media (prefers-reduced-motion: reduce) {
      * {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
      }
    }
  </style>
</head>
<body>
<div class="container">

  <!-- 案例1:导航下划线悬停动画 -->
  <section class="demo-section">
    <h2>📌 1. 导航下划线悬停动画</h2>
    <div class="demo-box" style="justify-content: flex-start;">
      <nav class="case1-nav">
        <a href="#">首页</a>
        <a href="#">产品</a>
        <a href="#">关于</a>
        <a href="#">联系</a>
      </nav>
    </div>
    <style>
      .case1-nav a {
        position: relative;
        text-decoration: none;
        color: #1e293b;
        font-weight: 500;
        padding: 8px 0;
        margin: 0 16px;
        transition: color 0.2s;
      }
      .case1-nav a::after {
        content: '';
        position: absolute;
        bottom: 0;
        left: 50%;
        width: 0;
        height: 2px;
        background: #3b82f6;
        transition: all 0.3s ease;
        transform: translateX(-50%);
      }
      .case1-nav a:hover {
        color: #3b82f6;
      }
      .case1-nav a:hover::after {
        width: 100%;
      }
    </style>
  </section>

  <!-- 案例2:纯CSS加载动画(旋转圆环) -->
  <section class="demo-section">
    <h2>⏳ 2. 纯CSS加载动画</h2>
    <div class="demo-box">
      <div class="case2-spinner"></div>
    </div>
    <style>
      .case2-spinner {
        width: 50px;
        height: 50px;
        border: 5px solid #e2e8f0;
        border-top-color: #3b82f6;
        border-radius: 50%;
        animation: case2-spin 0.8s linear infinite;
      }
      @keyframes case2-spin {
        to { transform: rotate(360deg); }
      }
    </style>
  </section>

  <!-- 案例3:3D卡片翻转 -->
  <section class="demo-section">
    <h2>🔄 3. 3D卡片翻转</h2>
    <div class="demo-box">
      <div class="case3-card-container">
        <div class="case3-card">
          <div class="case3-card-front">正面内容</div>
          <div class="case3-card-back">背面内容</div>
        </div>
      </div>
    </div>
    <style>
      .case3-card-container {
        width: 220px;
        height: 280px;
        perspective: 1200px;
      }
      .case3-card {
        position: relative;
        width: 100%;
        height: 100%;
        transform-style: preserve-3d;
        transition: transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
        border-radius: 16px;
      }
      .case3-card:hover {
        transform: rotateY(180deg);
      }
      .case3-card-front, .case3-card-back {
        position: absolute;
        width: 100%;
        height: 100%;
        backface-visibility: hidden;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 16px;
        font-weight: 600;
        box-shadow: 0 20px 30px -10px rgba(0,0,0,0.2);
      }
      .case3-card-front {
        background: linear-gradient(145deg, #3b82f6, #2563eb);
        color: white;
      }
      .case3-card-back {
        background: linear-gradient(145deg, #f97316, #ea580c);
        color: white;
        transform: rotateY(180deg);
      }
    </style>
  </section>

  <!-- 案例4:脉冲波纹(提醒效果) -->
  <section class="demo-section">
    <h2>🔴 4. 脉冲波纹</h2>
    <div class="demo-box">
      <div class="case4-pulse-dot"></div>
    </div>
    <style>
      .case4-pulse-dot {
        width: 24px;
        height: 24px;
        background: #ef4444;
        border-radius: 50%;
        box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.5);
        animation: case4-pulse 1.5s infinite;
      }
      @keyframes case4-pulse {
        to {
          box-shadow: 0 0 0 18px rgba(239, 68, 68, 0);
          transform: scale(1.1);
        }
      }
    </style>
  </section>

  <!-- 案例5:滚动渐入效果(需JavaScript) -->
  <section class="demo-section">
    <h2>📜 5. 滚动渐入效果(配合Intersection Observer)</h2>
    <p style="margin-bottom: 20px; color: #475569;">向下滚动,元素出现时渐入</p>
    <div class="case5-scroll-container" style="max-height: 300px; overflow-y: auto; border: 1px solid #cbd5e1; border-radius: 16px; padding: 16px; background: #f8fafc;">
      <div class="case5-scroll-item" style="height: 100px; background: #dbeafe; margin-bottom: 20px; display: flex; align-items: center; justify-content: center; border-radius: 12px;">第一个元素</div>
      <div class="case5-scroll-item" style="height: 100px; background: #dbeafe; margin-bottom: 20px; display: flex; align-items: center; justify-content: center; border-radius: 12px;">第二个元素</div>
      <div class="case5-scroll-item" style="height: 100px; background: #dbeafe; margin-bottom: 20px; display: flex; align-items: center; justify-content: center; border-radius: 12px;">第三个元素</div>
      <div class="case5-scroll-item" style="height: 100px; background: #dbeafe; margin-bottom: 20px; display: flex; align-items: center; justify-content: center; border-radius: 12px;">第四个元素</div>
      <div class="case5-scroll-item" style="height: 100px; background: #dbeafe; display: flex; align-items: center; justify-content: center; border-radius: 12px;">第五个元素</div>
    </div>
    <style>
      .case5-scroll-item {
        opacity: 0;
        transform: translateY(30px);
        transition: opacity 0.6s ease, transform 0.6s ease;
      }
      .case5-scroll-item.visible {
        opacity: 1;
        transform: translateY(0);
      }
    </style>
  </section>

  <!-- 案例6:手风琴折叠菜单(纯CSS) -->
  <section class="demo-section">
    <h2>🎹 6. 纯CSS手风琴折叠菜单</h2>
    <div class="demo-box" style="flex-direction: column; align-items: stretch; max-width: 400px; margin: 0 auto;">
      <div class="case6-accordion">
        <input type="checkbox" id="case6-item1" class="case6-checkbox">
        <label for="case6-item1" class="case6-label">📁 设计资源</label>
        <div class="case6-content">
          <p>图标库、UI套件、字体文件……</p>
        </div>
      </div>
      <div class="case6-accordion">
        <input type="checkbox" id="case6-item2" class="case6-checkbox">
        <label for="case6-item2" class="case6-label">⚙️ 开发工具</label>
        <div class="case6-content">
          <p>代码编辑器、终端、调试工具……</p>
        </div>
      </div>
      <div class="case6-accordion">
        <input type="checkbox" id="case6-item3" class="case6-checkbox">
        <label for="case6-item3" class="case6-label">📚 学习资料</label>
        <div class="case6-content">
          <p>文档、教程、实战项目……</p>
        </div>
      </div>
    </div>
    <style>
      .case6-accordion {
        margin-bottom: 12px;
        border: 1px solid #e2e8f0;
        border-radius: 14px;
        background: white;
        overflow: hidden;
      }
      .case6-checkbox {
        display: none;
      }
      .case6-label {
        display: block;
        padding: 16px 20px;
        background: #f1f5f9;
        cursor: pointer;
        font-weight: 600;
        transition: background 0.2s;
      }
      .case6-label:hover {
        background: #e2e8f0;
      }
      .case6-content {
        max-height: 0;
        overflow: hidden;
        padding: 0 20px;
        background: white;
        transition: max-height 0.3s ease-out, padding 0.2s;
      }
      .case6-checkbox:checked + .case6-label + .case6-content {
        max-height: 120px; /* 足够显示内容 */
        padding: 16px 20px;
      }
    </style>
  </section>

  <!-- 案例7:卡片图片悬停缩放 -->
  <section class="demo-section">
    <h2>🖼️ 7. 图片悬停缩放</h2>
    <div class="demo-box">
      <div class="case7-card">
        <div class="case7-image">
          <img src="https://picsum.photos/300/200?random=1" alt="示例图片" loading="lazy">
        </div>
        <p style="margin-top: 12px; font-weight: 500;">森林漫步</p>
      </div>
      <div class="case7-card">
        <div class="case7-image">
          <img src="https://picsum.photos/300/200?random=2" alt="示例图片" loading="lazy">
        </div>
        <p style="margin-top: 12px; font-weight: 500;">城市夜景</p>
      </div>
    </div>
    <style>
      .case7-card {
        width: 220px;
        text-align: center;
      }
      .case7-image {
        width: 220px;
        height: 150px;
        overflow: hidden;
        border-radius: 16px;
        box-shadow: 0 10px 15px -5px rgba(0,0,0,0.1);
      }
      .case7-image img {
        width: 100%;
        height: 100%;
        object-fit: cover;
        transition: transform 0.4s ease;
      }
      .case7-image:hover img {
        transform: scale(1.12);
      }
    </style>
  </section>

  <!-- 案例5 的 JavaScript(Intersection Observer) -->
  <script>
    (function() {
      // 只对案例5容器内的元素进行观察
      const container = document.querySelector('.case5-scroll-container');
      const items = container.querySelectorAll('.case5-scroll-item');
      const observer = new IntersectionObserver(entries => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            entry.target.classList.add('visible');
            // 可选:只触发一次
            observer.unobserve(entry.target);
          }
        });
      }, { threshold: 0.3, root: container }); // 在容器内滚动观察
      items.forEach(item => observer.observe(item));
    })();
  </script>
</div>
<!-- 额外说明:所有动画均可在现代浏览器运行,性能优化建议已内联 -->
</body>
</html>

使用说明

  • 将上述代码完整复制,保存为 .html 文件,用浏览器打开即可查看所有案例。
  • 每个案例的样式都被限定在对应的类名下,互不影响。
  • 案例5(滚动渐入)在一个固定高度的可滚动容器内演示,需滚动观察效果。
  • 页面底部包含 prefers-reduced-motion 媒体查询,尊重用户系统级动画减少设置。

如果需要单独提取某个案例的代码,可直接从相应 <style> 和 HTML 结构中复制。

如果这篇文章让你对 CSS 刮目相看,点个赞,收藏下,让更多朋友看到——CSS动画效果也不赖。

#CSS #前端 #Web开发 #设计 #干货