CSS & 布局体系 · 48/102
1. 自适应高度布局 2. 链接伪类执行顺序 3. Bootstrap 浮动与清除浮动 4. Bootstrap 框架介绍 5. Base64 图片的使用场景 6. Bootstrap 网格列间距 7. Bootstrap 网格系统工作原理 8. Bootstrap 网格系统 9. Bootstrap 图片样式类 10. Bootstrap 响应式 class 前缀 11. 浏览器 CSS 选择器解析机制 12. Bootstrap 文字对齐方式 13. 浏览器最小字体检测 14. CheckBox 美化方法 15. Chrome密码自动填充背景色修改 16. 屏幕阅读器隐藏元素 17. BFC 块级格式化上下文 18. CSS 盒模型 19. 垂直水平居中方案 20. 清除浮动方法 21. CSS 代码合并方法 22. CSS content 属性用法 23. CSS Content 属性作用 24. display 属性值及其作用 25. CSS 绘制几何图形 26. CSS 硬件加速触发方式 27. CSS 工程化实践 28. Flex 弹性布局 29. Grid 网格布局 30. CSS Hack 原理与应用 31. 绘制 0.5px 细线 32. CSS 隐藏元素方式 33. CSS 可继承与不可继承属性 34. CSS 继承属性 35. 改变页面布局的 CSS 属性 36. CSS 长度单位对比 37. CSS 无限循环动画 38. CSS 模块化的实现方式 39. 样式模块化编写 40. CSS Modules 与 CSS-in-JS 41. CSS 为何不支持父选择器 42. CSS 性能优化 43. Position 属性值 44. CSS 选择器权重 45. CSS 选择符与继承属性 46. 多栏布局方案 47. CSS 样式初始化的必要性 48. CSS 幻灯片效果实现 49. CSS Sprites 的优缺点 50. CSS 动画与 JS 动画的区别 51. 文字重叠的 CSS 属性 52. CSS3 新特性 53. CSSOM 与 DOM 的解析时机 54. CSS3 新增伪类 55. 自定义字体使用场景 56. CSS 预处理器对比 57. 设备像素与 CSS 像素的区别 58. 禁用移动端滑动手势 59. display、float、position 的关系 60. div+css 布局相比 table 的优点 61. 浮动元素的 display 值变化 62. 等高布局实现方案 63. 浮动元素的块级化 64. 浮动元素问题与解决 65. 字体清晰度与细度优化 66. 浮动元素垂直居中 67. font-style 的 oblique 属性 68. FOUC 无样式闪烁及其避免 69. 全屏滚动原理与CSS属性 70. 原生 JS 实现图标边框切换 71. 行内元素与块级元素的区别 72. HTML 和 CSS 中的图片加载与渲染 73. JavaScript 动画与 CSS 动画的区别 74. JS 与 CSS 对 DOM 构建的影响 75. inline-block 元素间隙问题 76. inline-block 间隙问题 77. line-height 的继承与计算 78. link 与 @import 的区别 79. 列表项间隔空白问题 80. 移动端适配方案 81. CSS 实现视差滚动效果 82. Margin 与 Padding 使用场景 83. 外边距重叠现象 84. CSS object-fit 属性用法 85. 百分比高度相对计算 86. position: dbpnk 定位 87. 品字布局设计 88. 伪类与伪元素的区别 89. 伪元素 ::before 和 ::after 的使用 90. px 与 em 单位区别 91. 响应式设计原理与IE兼容 92. 宽高自适应正方形实现 93. 回流与重绘 94. 层叠上下文与 z-index 95. 小于 12px 字体实现 96. RGBA 与 Opacity 透明度对比 97. rgba 与 opacity 透明度对比 98. 单行文本两端对齐 99. 文本溢出省略样式 100. 网页字体大小选择 101. 网页字体大小奇偶选择 102. WXSS 与 CSS 的区别

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 实现堆叠布局