分享一个横向滚动案例,带悬停暂停,通用性很强

写在前面

在一些网站里,经常能看到"项目展示"、"合作伙伴 Logo 墙"、"新闻滚动条"这类横向滚动的展示效果。

今天分享一个用 HTML + CSS + JS 实现的简单案例,效果自然流畅,还支持悬停暂停 ,效果如下:

1. 基础结构

HTML 结构很简单,可以理解为三层:

  • 最外层容器:负责限制可见范围。
  • 滚动内容容器:用于包裹滚动的元素。
  • 具体的滚动项:展示的卡片(图片+文字)。

源码如下:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>横向自动滚动(不使用rem)</title>
    <style>
      /* 基础样式重置 */
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        font-family: 'Arial', sans-serif;
      }

      body {
        background-color: #f5f5f5;
        padding: 30px;
      }

      .container {
        max-width: 1200px;
        margin: 0 auto;
      }

      h2 {
        color: #333;
        text-align: center;
        margin-bottom: 30px;
        font-size: 32px;
      }

      /* 滚动容器样式 */
      .scroll-container {
        overflow: hidden;
        position: relative;
        background-color: white;
        border-radius: 8px;
        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
        padding: 30px;
      }

      .scroll-content2 {
        display: flex;
      }

      /* 滚动内容样式 */
      .scroll-content {
        display: flex;
        animation: scroll 3s linear infinite;
      }

      /* 滚动项样式 */
      .scroll-item {
        width: 300px;
        margin-right: 24px;
        flex-shrink: 0;
        background-color: #f0f7ff;
        border-radius: 6px;
        padding: 15px;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
        transition: box-shadow 0.3s ease;
      }

      .scroll-item:hover {
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
      }

      .scroll-item img {
        width: 100%;
        height: 180px;
        object-cover: cover;
        border-radius: 4px;
        margin-bottom: 15px;
      }

      .scroll-item h3 {
        color: #333;
        font-size: 18px;
        margin-bottom: 8px;
      }

      .scroll-item p {
        color: #666;
        font-size: 14px;
      }

      /* 滚动动画 */
      @keyframes scroll {
        0% {
          transform: translateX(0);
        }
        100% {
          transform: translateX(-100%); /* 减去一半间距以实现无缝滚动 */
        }
      }

      /* 暂停动画的类 */
      .scroll-paused {
        animation-play-state: paused;
      }

      .info-text {
        text-align: center;
        color: #666;
        margin-top: 20px;
        font-size: 14px;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <h2>横向自动滚动展示</h2>

      <!-- 滚动容器 -->
      <div class="scroll-container" id="scrollContainer">
        <div class="scroll-content2">
          <div class="scroll-content" id="scrollContent">
            <!-- 滚动项 - 第一组 -->
            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=1" alt="示例图片1" />
              <h3>项目 1</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>

            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=2" alt="示例图片2" />
              <h3>项目 2</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>

            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=3" alt="示例图片3" />
              <h3>项目 3</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>

            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=4" alt="示例图片4" />
              <h3>项目 4</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>

            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=5" alt="示例图片5" />
              <h3>项目 5</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>
          </div>
          <!-- 重复第一组项目以实现无缝滚动效果 -->
          <div class="scroll-content" id="scrollContent2">
            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=1" alt="示例图片1" />
              <h3>项目 1</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>

            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=2" alt="示例图片2" />
              <h3>项目 2</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>

            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=3" alt="示例图片3" />
              <h3>项目 3</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>

            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=4" alt="示例图片4" />
              <h3>项目 4</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>

            <div class="scroll-item">
              <img src="https://picsum.photos/400/200?random=5" alt="示例图片5" />
              <h3>项目 5</h3>
              <p>这是一个滚动展示的项目示例</p>
            </div>
          </div>
        </div>
      </div>

      <p class="info-text">鼠标悬停在滚动区域上可暂停滚动</p>
    </div>

    <script>
      // 获取滚动容器和内容元素
      const scrollContainer = document.getElementById('scrollContainer')
      const scrollContent = document.getElementById('scrollContent') // 容器一
      const scrollContent2 = document.getElementById('scrollContent2')//容器二
      // 鼠标悬停时暂停滚动
      scrollContainer.addEventListener('mouseenter', () => {
        scrollContent.classList.add('scroll-paused')
        scrollContent2.classList.add('scroll-paused')
      })

      // 鼠标离开时继续滚动
      scrollContainer.addEventListener('mouseleave', () => {
        scrollContent.classList.remove('scroll-paused')
        scrollContent2.classList.remove('scroll-paused')
      })
    </script>
  </body>
</html>

📌 这里的关键点是:滚动内容要写两份,第一份结束时第二份紧跟上,就能形成"无缝衔接"的效果。、

大致过程如下:

复制代码
 首先是两组相同内容并排放置
 动画让整体向左移动
 移动距离 = 一组内容的宽度
 第一组移出时第二组正好进入
 动画结束时重置到初始状态
 无限循环形成连续滚动

2. 样式拆解

核心样式在于三个部分:

  1. 容器限制宽度 + 隐藏溢出
css 复制代码
.scroll-container {
  overflow: hidden;
  position: relative;
  background-color: white;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  padding: 30px;
}

这样只会看到一屏的内容,超出的部分会被隐藏。

  1. 滚动内容横向排列
css 复制代码
.scroll-content {
  display: flex;
  animation: scroll 20s linear infinite;
}

设置 display: flex 后,子元素会自然横排,再配合 animation 实现自动滚动。

  1. 动画关键帧
css 复制代码
@keyframes scroll {
  0% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-100%);
  }
}

整个内容不断向左平移,从 0 移动到 -100% 的位置,循环播放。


3. 鼠标悬停暂停

为了用户体验,最好加一个"悬停暂停"。

通过 JS 控制 animation-play-state

JS 复制代码
      // 获取滚动容器和内容元素
      const scrollContainer = document.getElementById('scrollContainer')
      const scrollContent = document.getElementById('scrollContent') // 容器一
      const scrollContent2 = document.getElementById('scrollContent2') // 容器2
      // 鼠标悬停时暂停滚动
      scrollContainer.addEventListener('mouseenter', () => {
        scrollContent.classList.add('scroll-paused')
        scrollContent2.classList.add('scroll-paused')
      })

      // 鼠标离开时继续滚动
      scrollContainer.addEventListener('mouseleave', () => {
        scrollContent.classList.remove('scroll-paused')
        scrollContent2.classList.remove('scroll-paused')
      })

CSS 中加一个辅助类:

css 复制代码
.scroll-paused {
  animation-play-state: paused;
}

这样当鼠标移上去时,滚动会停下来,移开后继续。

5. 小结与优化思路

  • 适用场景:展示案例、Logo 墙、新闻条、商品推荐等。
  • 无缝循环:记得复制一份内容,不然会出现"空白断层"。
  • 流畅性 :尽量用 transform: translateX,性能更好。
  • 交互优化:可以加上触摸滑动、点击切换等功能,适配移动端。
相关推荐
MariaH2 小时前
git rebase的使用
前端
_柳青杨2 小时前
深入理解 JavaScript 事件循环
前端·javascript
阡陌Jony2 小时前
关于前端性能优化的一些问题:
前端
用户600071819103 小时前
【翻译】简化 TSRX
前端
IT乐手4 小时前
佛德角逼平西班牙,国足还有啥借口?
前端
JustHappy4 小时前
我汇总了身边朋友的经历才发现,其实第一份实习是最难找的......
前端·后端·面试
星栈4 小时前
Dioxus 的响应式系统:`Signal`、`Memo`、`Effect` 和异步状态到底该怎么分工
前端·前端框架
yingyima4 小时前
Java 正则表达式:比你想象的更强大
前端
yuanyxh7 小时前
macOS 应用 - 纯对话生成
前端·macos·ai编程