You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Div容器的左右无限循环滚动功能?

实现滚动容器的无限循环滚动功能

问题描述

我有一个包含多个scroll-item的scroll-layout容器,配有scroll-left和scroll-right两个按钮,目前已经通过JavaScript实现了基础的平滑滚动功能(代码如下)。现在需要实现左右无限循环滚动:滚动到8号scroll-item后,继续显示1号并以此循环;向左滚动到1号后,继续显示8号,实现无间断的滚动效果。

现有代码

HTML

<div class="scroll-container">
  <div class="scroll-layout">
    <div class="scroll-item">1</div>
    <div class="scroll-item">2</div>
    <div class="scroll-item">3</div>
    <div class="scroll-item">4</div>
    <div class="scroll-item">5</div>
    <div class="scroll-item">6</div>
    <div class="scroll-item">7</div>
    <div class="scroll-item">8</div>
  </div>
  <button class="scroll-button left" id="scroll-left"> ◀</button>
  <button class="scroll-button right" id="scroll-right"> ▶</button>
</div>

JavaScript

const scrollContainer = document.querySelector('.scroll-layout');
const scrollLeftButton = document.getElementById('scroll-left');
const scrollRightButton = document.getElementById('scroll-right');

scrollLeftButton.addEventListener('click', () => {
  scrollContainer.scrollBy({
    left: -200, // Adjust the scroll amount as needed
    behavior: 'smooth' // Enable smooth scrolling
  });
});

scrollRightButton.addEventListener('click', () => {
  scrollContainer.scrollBy({
    left: 200, // Adjust the scroll amount as needed
    behavior: 'smooth' // Enable smooth scrolling
  });
});

解决方案

无限循环滚动的核心思路是克隆容器首尾元素并插入到另一端,当滚动到边界时瞬间切换到克隆内容的对应位置,让用户感知不到跳转,从而实现循环效果。以下是完整实现代码:

1. 补充基础CSS样式

确保容器和元素的布局支持横向滚动:

.scroll-container {
  position: relative;
  width: 800px; /* 根据需求调整可视区域宽度 */
  overflow: hidden; /* 隐藏超出可视区域的内容 */
}

.scroll-layout {
  display: flex;
  gap: 10px; /* 控制item之间的间距 */
  overflow-x: auto;
  scroll-behavior: smooth; /* 保持平滑滚动特性 */
  padding: 10px 0;
  /* 隐藏原生滚动条(可选) */
  scrollbar-width: none;
}
.scroll-layout::-webkit-scrollbar {
  display: none;
}

.scroll-item {
  width: 200px; /* 单个item宽度,需和JS滚动量对应 */
  height: 150px;
  background: #f0f0f0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  flex-shrink: 0; /* 禁止item被压缩 */
}

.scroll-button {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  border: none;
  background: rgba(0,0,0,0.5);
  color: white;
  font-size: 20px;
  cursor: pointer;
  z-index: 10;
}
.scroll-button.left {
  left: 10px;
}
.scroll-button.right {
  right: 10px;
}

2. 修改JavaScript实现循环逻辑

const scrollContainer = document.querySelector('.scroll-layout');
const scrollLeftButton = document.getElementById('scroll-left');
const scrollRightButton = document.getElementById('scroll-right');
const scrollItems = document.querySelectorAll('.scroll-item');
// 计算单个item的实际宽度(含间距)
const itemWidth = scrollItems[0].offsetWidth + parseInt(getComputedStyle(scrollContainer).gap);
const scrollAmount = itemWidth; // 每次滚动一个item的宽度

// 克隆首尾元素,插入到容器另一端
function cloneItems() {
  const firstItem = scrollItems[0].cloneNode(true);
  const lastItem = scrollItems[scrollItems.length - 1].cloneNode(true);
  scrollContainer.appendChild(firstItem);
  scrollContainer.insertBefore(lastItem, scrollItems[0]);
}

// 初始化滚动状态:克隆元素并定位到原第一个item位置
function initScroll() {
  cloneItems();
  scrollContainer.scrollLeft = itemWidth; // 跳过开头克隆的最后一个item
}

// 监听滚动事件,处理边界跳转
scrollContainer.addEventListener('scroll', () => {
  // 滚动到最右侧克隆的第一个item时,跳转到原第一个item位置
  if (scrollContainer.scrollLeft >= scrollContainer.scrollWidth - itemWidth * 2) {
    scrollContainer.scrollBehavior = 'auto'; // 关闭平滑滚动,瞬间跳转
    scrollContainer.scrollLeft = itemWidth;
    // 恢复平滑滚动
    setTimeout(() => {
      scrollContainer.scrollBehavior = 'smooth';
    }, 0);
  }
  // 滚动到最左侧克隆的最后一个item时,跳转到原最后一个item位置
  if (scrollContainer.scrollLeft <= 0) {
    scrollContainer.scrollBehavior = 'auto';
    scrollContainer.scrollLeft = scrollContainer.scrollWidth - itemWidth * 2;
    setTimeout(() => {
      scrollContainer.scrollBehavior = 'smooth';
    }, 0);
  }
});

// 左侧按钮点击事件
scrollLeftButton.addEventListener('click', () => {
  scrollContainer.scrollBy({
    left: -scrollAmount,
    behavior: 'smooth'
  });
});

// 右侧按钮点击事件
scrollRightButton.addEventListener('click', () => {
  scrollContainer.scrollBy({
    left: scrollAmount,
    behavior: 'smooth'
  });
});

// 启动初始化
initScroll();

关键逻辑说明

  • 克隆元素:将第一个item克隆到容器末尾,最后一个item克隆到容器开头,确保滚动到边界时视觉上能衔接原内容。
  • 初始定位:初始化时直接滚动到原第一个item的位置,避免用户看到克隆的元素。
  • 边界跳转:监听滚动位置,当触发边界时关闭平滑滚动,瞬间切换到对应原元素位置,再恢复平滑滚动,实现无感知循环。
  • 动态计算滚动量:通过元素实际宽度和间距计算滚动距离,避免固定值导致的适配问题。

内容的提问来源于stack exchange,提问作者Theo 17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 00:22:50