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

如何基于Bootstrap实现不同断点适配的响应式多列轮播

通过JS动态重组轮播项结构实现,无需重复编写两套DOM,完全兼容Bootstrap5原生轮播逻辑,适配规则如下:

  • 视口宽度≥576px(sm及以上断点):每个轮播项展示3个内容块,共2个轮播项
  • 视口宽度<576px(sm以下断点):每个轮播项展示2个内容块,共3个轮播项

核心实现逻辑

  • 抽离所有内容块为独立配置项,避免硬编码在固定轮播项中无法灵活拆分
  • 监听视口宽度变化,仅在跨越sm断点(576px)时触发轮播结构重绘,搭配防抖控制避免性能损耗
  • 重绘时按当前断点规则分组内容块,动态生成对应数量的轮播项,自动匹配栅格class
  • 重绘前销毁已存在的轮播实例,避免原生组件事件冲突

完整可运行代码

.box{
  min-height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
}
.r{ background-color: red; }
.g{ background-color: gray; }
.b{ background-color: blue; }
<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Bootstrap Carousel响应式适配</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
</head>
<body>
  <div class="container py-5">
    <div id="carouselExampleControls" class="carousel slide carousel-dark" data-bs-ride="true">
      <div class="carousel-inner">
        <!-- 轮播项由JS动态渲染,无需硬编码 -->
      </div>
      <button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleControls" data-bs-slide="prev">
        <span class="carousel-control-prev-icon" aria-hidden="true"></span>
        <span class="visually-hidden">上一个</span>
      </button>
      <button class="carousel-control-next" type="button" data-bs-target="#carouselExampleControls" data-bs-slide="next">
        <span class="carousel-control-next-icon" aria-hidden="true"></span>
        <span class="visually-hidden">下一个</span>
      </button>
    </div>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
  <script>
    // 原始内容块配置
    const slideItems = [
      {text: 'Hello', colorClass: 'r'},
      {text: 'Hello1', colorClass: 'g'},
      {text: 'Hello2', colorClass: 'b'},
      {text: 'Hello3', colorClass: 'r'},
      {text: 'Hello4', colorClass: 'g'},
      {text: 'Hello5', colorClass: 'b'}
    ]
    const carouselEl = document.getElementById('carouselExampleControls')
    const carouselInnerEl = carouselEl.querySelector('.carousel-inner')
    let carouselInstance = null
    let lastRenderType = null // 记录上一次渲染类型:'lg'(3块/项) 或 'sm'(2块/项)

    // 防抖函数
    function debounce(func, delay = 200) {
      let timer = null
      return function(...args) {
        clearTimeout(timer)
        timer = setTimeout(() => func.apply(this, args), delay)
      }
    }

    // 渲染轮播结构
    function renderCarousel() {
      const isLg = window.innerWidth >= 576
      const currentType = isLg ? 'lg' : 'sm'
      // 未跨断点时不重新渲染
      if (currentType === lastRenderType) return
      lastRenderType = currentType

      const perView = isLg ? 3 : 2
      const colClass = isLg ? 'col-sm-4' : 'col-6'

      // 清空现有轮播内容
      carouselInnerEl.innerHTML = ''
      // 销毁旧的轮播实例
      if (carouselInstance) {
        carouselInstance.dispose()
      }

      // 分组内容块
      const groups = []
      for (let i = 0; i < slideItems.length; i += perView) {
        groups.push(slideItems.slice(i, i + perView))
      }

      // 生成轮播项
      groups.forEach((group, index) => {
        const itemEl = document.createElement('div')
        itemEl.className = `carousel-item ${index === 0 ? 'active' : ''}`
        const rowEl = document.createElement('div')
        rowEl.className = 'row'

        group.forEach(item => {
          const colEl = document.createElement('div')
          colEl.className = `${colClass} box ${item.colorClass}`
          colEl.textContent = item.text
          rowEl.appendChild(colEl)
        })

        itemEl.appendChild(rowEl)
        carouselInnerEl.appendChild(itemEl)
      })

      // 重新初始化轮播
      carouselInstance = new bootstrap.Carousel(carouselEl, {
        ride: true,
        interval: false // 需要自动轮播可改为对应毫秒数,比如3000即3秒切换一次
      })
    }

    // 首次加载渲染
    renderCarousel()
    // 监听窗口变化
    window.addEventListener('resize', debounce(renderCarousel))
  </script>
</body>
</html>

扩展说明

  • 如果后续需要增减内容块,只需要修改slideItems数组配置即可,无需调整其他逻辑
  • 断点阈值、每屏展示数量、栅格class都可以根据实际业务需求修改,逻辑通用
  • 切换动画完全沿用Bootstrap原生轮播效果,和参考站点交互逻辑一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 13:33:23