CSS 幻灯片效果实现

使用纯 CSS 实现自动轮播的幻灯片效果

问题

请用 CSS 写一个简单的幻灯片效果页面。

解答

方案一:CSS 动画实现自动轮播

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS 幻灯片</title>
  <style>
    /* 容器设置 */
    .slider {
      width: 600px;
      height: 400px;
      overflow: hidden;
      position: relative;
      margin: 50px auto;
      border-radius: 8px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
    }

    /* 幻灯片轨道 */
    .slides {
      display: flex;
      width: 400%; /* 4张图片,每张100% */
      height: 100%;
      animation: slide 12s infinite; /* 12秒循环 */
    }

    /* 单张幻灯片 */
    .slide {
      width: 25%; /* 100% / 4张 */
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 48px;
      color: white;
      font-weight: bold;
    }

    /* 不同颜色区分 */
    .slide:nth-child(1) { background: #e74c3c; }
    .slide:nth-child(2) { background: #3498db; }
    .slide:nth-child(3) { background: #2ecc71; }
    .slide:nth-child(4) { background: #9b59b6; }

    /* 轮播动画 */
    @keyframes slide {
      0%, 20%   { transform: translateX(0); }      /* 停留在第1张 */
      25%, 45%  { transform: translateX(-25%); }   /* 停留在第2张 */
      50%, 70%  { transform: translateX(-50%); }   /* 停留在第3张 */
      75%, 95%  { transform: translateX(-75%); }   /* 停留在第4张 */
      100%      { transform: translateX(0); }      /* 回到第1张 */
    }
  </style>
</head>
<body>
  <div class="slider">
    <div class="slides">
      <div class="slide">Slide 1</div>
      <div class="slide">Slide 2</div>
      <div class="slide">Slide 3</div>
      <div class="slide">Slide 4</div>
    </div>
  </div>
</body>
</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 幻灯片 - 带指示器</title>
  <style>
    .slider {
      width: 600px;
      height: 400px;
      position: relative;
      margin: 50px auto;
      border-radius: 8px;
      overflow: hidden;
    }

    /* 使用层叠 + 透明度切换 */
    .slide {
      position: absolute;
      width: 100%;
      height: 100%;
      opacity: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 48px;
      color: white;
      font-weight: bold;
      transition: opacity 0.5s ease-in-out;
    }

    .slide:nth-child(1) { background: #e74c3c; animation: fade 12s infinite 0s; }
    .slide:nth-child(2) { background: #3498db; animation: fade 12s infinite 3s; }
    .slide:nth-child(3) { background: #2ecc71; animation: fade 12s infinite 6s; }
    .slide:nth-child(4) { background: #9b59b6; animation: fade 12s infinite 9s; }

    /* 淡入淡出动画 */
    @keyframes fade {
      0%, 20%  { opacity: 1; z-index: 1; }  /* 显示 */
      25%, 100% { opacity: 0; z-index: 0; } /* 隐藏 */
    }

    /* 悬停暂停 */
    .slider:hover .slide {
      animation-play-state: paused;
    }

    /* 指示器 */
    .indicators {
      position: absolute;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      display: flex;
      gap: 10px;
      z-index: 10;
    }

    .indicator {
      width: 12px;
      height: 12px;
      border-radius: 50%;
      background: rgba(255, 255, 255, 0.5);
      animation: dot 12s infinite;
    }

    .indicator:nth-child(1) { animation-delay: 0s; }
    .indicator:nth-child(2) { animation-delay: 3s; }
    .indicator:nth-child(3) { animation-delay: 6s; }
    .indicator:nth-child(4) { animation-delay: 9s; }

    @keyframes dot {
      0%, 20%  { background: white; transform: scale(1.2); }
      25%, 100% { background: rgba(255, 255, 255, 0.5); transform: scale(1); }
    }

    .slider:hover .indicator {
      animation-play-state: paused;
    }
  </style>
</head>
<body>
  <div class="slider">
    <div class="slide">Slide 1</div>
    <div class="slide">Slide 2</div>
    <div class="slide">Slide 3</div>
    <div class="slide">Slide 4</div>
    <div class="indicators">
      <span class="indicator"></span>
      <span class="indicator"></span>
      <span class="indicator"></span>
      <span class="indicator"></span>
    </div>
  </div>
</body>
</html>

方案三:纯 CSS 点击切换(使用 radio)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS 幻灯片 - 点击切换</title>
  <style>
    .slider {
      width: 600px;
      height: 400px;
      position: relative;
      margin: 50px auto;
      border-radius: 8px;
      overflow: hidden;
    }

    /* 隐藏 radio */
    .slider input {
      display: none;
    }

    .slide {
      position: absolute;
      width: 100%;
      height: 100%;
      opacity: 0;
      transition: opacity 0.5s;
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 48px;
      color: white;
      font-weight: bold;
    }

    .slide:nth-child(2) { background: #e74c3c; }
    .slide:nth-child(3) { background: #3498db; }
    .slide:nth-child(4) { background: #2ecc71; }
    .slide:nth-child(5) { background: #9b59b6; }

    /* radio 选中时显示对应幻灯片 */
    #s1:checked ~ .slide:nth-child(2),
    #s2:checked ~ .slide:nth-child(3),
    #s3:checked ~ .slide:nth-child(4),
    #s4:checked ~ .slide:nth-child(5) {
      opacity: 1;
      z-index: 1;
    }

    /* 导航按钮 */
    .nav {
      position: absolute;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      display: flex;
      gap: 10px;
      z-index: 10;
    }

    .nav label {
      width: 14px;
      height: 14px;
      border-radius: 50%;
      background: rgba(255, 255, 255, 0.5);
      cursor: pointer;
      transition: background 0.3s;
    }

    .nav label:hover {
      background: rgba(255, 255, 255, 0.8);
    }

    /* 选中状态 */
    #s1:checked ~ .nav label[for="s1"],
    #s2:checked ~ .nav label[for="s2"],
    #s3:checked ~ .nav label[for="s3"],
    #s4:checked ~ .nav label[for="s4"] {
      background: white;
      transform: scale(1.2);
    }
  </style>
</head>
<body>
  <div class="slider">
    <!-- radio 控制 -->
    <input type="radio" name="slider" id="s1" checked>
    <input type="radio" name="slider" id="s2">
    <input type="radio" name="slider" id="s3">
    <input type="radio" name="slider" id="s4">
    
    <!-- 幻灯片 -->
    <div class="slide">Slide 1</div>
    <div class="slide">Slide 2</div>
    <div class="slide">Slide 3</div>
    <div class="slide">Slide 4</div>
    
    <!-- 导航 -->
    <div class="nav">
      <label for="s1"></label>
      <label for="s2"></label>
      <label for="s3"></label>
      <label for="s4"></label>
    </div>
  </div>
</body>
</html>

关键点

  • 方案一:使用 transform: translateX() 配合 @keyframes 实现水平滑动,通过百分比控制停留时间
  • 方案二:使用 opacityanimation-delay 实现淡入淡出,animation-play-state: paused 实现悬停暂停
  • 方案三:利用 input:checked 选择器配合兄弟选择器 ~ 实现点击切换,无需 JavaScript
  • 动画时间计算:总时长 / 幻灯片数量 = 每张停留时间,关键帧百分比据此分配
  • 层叠控制:使用 z-indexopacity 控制显示层级,position: absolute 实现堆叠布局