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

如何基于现有布局构建自定义Carousel轮播组件?

自定义轮播实现方案(适配你的现有布局)

问题背景

正在构建静态HTML/CSS网站,需要为客户 testimonial 板块添加轮播功能。现有布局下,之前尝试的教程要么和当前结构不兼容,要么基于Swiper JS实现,但Swiper的样式定制(位置、颜色等)成本太高。以下是适配后的完整实现方案。


调整后的HTML代码

<section class="section-customers wrapper">
  <div class="container caraseoul">
    <!-- 新增容器包裹所有slide,用于控制滚动 -->
    <div class="slides-container">
      <div class="slide">
        <img
          src="./images/customers/ryan-hoffman.jpg"
          alt="ryan-hoffman"
          class="customer-img"
        />
        <blockquote class="testimonial">
          <p class="testimonial-text">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Ratione
            excepturi sint sequi laborum, nostru,excepturi sint sequi
            laborum, nostru,excepturi sint sequi laborum, nostru
          </p>
          <p class="testimonial-author">Ryan Hoffman</p>
          <p class="testimonial-status">
            <span>30 </span>kgs lost in 7 months
          </p>
        </blockquote>
      </div>
      <div class="slide">
        <img
          src="./images/customers/alexander.jpg"
          alt="alexander"
          class="customer-img"
        />
        <blockquote class="testimonial">
          <p class="testimonial-text">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Ratione
            excepturi sint sequi laborum, nostru,excepturi sint sequi
            laborum, nostru,excepturi sint sequi laborum, nostru
          </p>
          <p class="testimonial-author">Alexander Hamilton</p>
          <p class="testimonial-status">
            <span>10 </span>kgs lost in 2 months
          </p>
        </blockquote>
      </div>
      <div class="slide">
        <img
          src="./images/customers/edward.jpg"
          alt="edward"
          class="customer-img"
        />
        <blockquote class="testimonial">
          <p class="testimonial-text">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Ratione
            excepturi sint sequi laborum, nostru,excepturi sint sequi
            laborum, nostru,excepturi sint sequi laborum, nostru
          </p>
          <p class="testimonial-author">Cristina Niosi</p>
          <p class="testimonial-status">
            <span>23 </span>kgs lost in 6 months
          </p>
        </blockquote>
      </div>
      <div class="slide">
        <img
          src="./images/customers/edward.jpg"
          alt="edward"
          class="customer-img"
        />
        <blockquote class="testimonial">
          <p class="testimonial-text">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Ratione
            excepturi sint sequi laborum, nostru,excepturi sint sequi
            laborum, nostru,excepturi sint sequi laborum, nostru
          </p>
          <p class="testimonial-author">Cristina Niosi</p>
          <p class="testimonial-status">
            <span>23 </span>kgs lost in 6 months
          </p>
        </blockquote>
      </div>
      <div class="slide">
        <img
          src="./images/customers/edward.jpg"
          alt="edward"
          class="customer-img"
        />
        <blockquote class="testimonial">
          <p class="testimonial-text">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Ratione
            excepturi sint sequi laborum, nostru,excepturi sint sequi
            laborum, nostru,excepturi sint sequi laborum, nostru
          </p>
          <p class="testimonial-author">Cristina Niosi</p>
          <p class="testimonial-status">
            <span>23 </span>kgs lost in 6 months
          </p>
        </blockquote>
      </div>
      <div class="slide">
        <img
          src="./images/customers/edward.jpg"
          alt="edward"
          class="customer-img"
        />
        <blockquote class="testimonial">
          <p class="testimonial-text">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Ratione
            excepturi sint sequi laborum, nostru,excepturi sint sequi
            laborum, nostru,excepturi sint sequi laborum, nostru
          </p>
          <p class="testimonial-author">Cristina Niosi</p>
          <p class="testimonial-status">
            <span>23 </span>kgs lost in 6 months
          </p>
        </blockquote>
      </div>
      <div class="slide">
        <img
          src="./images/customers/edward.jpg"
          alt="edward"
          class="customer-img"
        />
        <blockquote class="testimonial">
          <p class="testimonial-text">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Ratione
            excepturi sint sequi laborum, nostru,excepturi sint sequi
            laborum, nostru,excepturi sint sequi laborum, nostru
          </p>
          <p class="testimonial-author">Cristina Niosi</p>
          <p class="testimonial-status">
            <span>23 </span>kgs lost in 6 months
          </p>
        </blockquote>
      </div>
    </div>
    <button class="slider-btn slider-btn-right">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        fill="none"
        viewBox="0 0 24 24"
        stroke-width="1.5"
        stroke="currentColor"
        class="btn-icon"
      >
        <path
          stroke-linecap="round"
          stroke-linejoin="round"
          d="M8.25 4.5l7.5 7.5-7.5 7.5"
        />
      </svg>
    </button>
    <button class="slider-btn slider-btn-left">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        fill="none"
        viewBox="0 0 24 24"
        stroke-width="1.5"
        stroke="currentColor"
        class="btn-icon"
      >
        <path
          stroke-linecap="round"
          stroke-linejoin="round"
          d="M15.75 19.5L8.25 12l7.5-7.5"
        />
      </svg>
    </button>
  </div>
</section>

适配轮播的CSS代码

/* TESTIMONIAL SECTION  CSS*/
.section-customers {
  padding: 9.6rem 0;
  background-color: #fed2d2;
}

.customer-img {
  max-width: 100%;
  height: 10rem;
  width: 10rem;
  border-radius: 50%;
  box-shadow: rgba(6, 24, 44, 0.4) 0px 0px 0px 2px,
    rgba(6, 24, 44, 0.65) 0px 4px 6px -1px,
    rgba(255, 255, 255, 0.08) 0px 1px 0px inset;
}

.caraseoul {
  display: flex;
  gap: 4.8rem;
  position: relative;
  overflow: hidden; /* 隐藏超出容器的slide */
}

/* 新增轮播容器,控制slide滚动 */
.slides-container {
  display: flex;
  gap: 4.8rem; /* 和外层gap保持一致 */
  transition: transform 0.5s ease-in-out; /* 滑动过渡动画 */
}

.testimonial {
  color: black;
}

.slide {
  flex: 0 0 auto; /* 固定宽度,不压缩不拉伸 */
  width: calc((100% - 9.6rem) / 3); /* 一行显示3个slide,减去两个gap的宽度 */
  display: flex;
  flex-direction: column;
  gap: 1.4rem;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 5rem 0;
  background-color: white;
  border-radius: 6px;
  box-shadow: rgba(0, 0, 0, 0.35) 0px 5px 15px;
}

.testimonial-text {
  font-size: 1.2rem;
  margin: 2rem;
  margin-top: auto;
}

.testimonial-author {
  font-size: 2rem;
  font-weight: 400;
  margin-bottom: 0.6rem;
  color: navy;
}

.testimonial-status {
  font-size: 1.8rem;
}

.testimonial-status span {
  color: #a12222;
  font-weight: 600;
}

.slider-btn {
  position: absolute;
  background-color: white;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.8rem;
  border: none;
  cursor: pointer;
  z-index: 10;
}

.btn-icon {
  height: 2.4rem;
  width: 2.4rem;
  stroke: #a12222;
}

.slider-btn-left {
  left: 2%; /* 调整位置避免超出可视区域 */
  top: 50%;
  transform: translate(0, -50%);
}
.slider-btn-right {
  right: 2%;
  top: 50%;
  transform: translate(0, -50%);
}

JavaScript 轮播逻辑

在HTML末尾添加以下脚本,实现手动切换和自动轮播:

document.addEventListener('DOMContentLoaded', function() {
  const slidesContainer = document.querySelector('.slides-container');
  const slides = document.querySelectorAll('.slide');
  const btnLeft = document.querySelector('.slider-btn-left');
  const btnRight = document.querySelector('.slider-btn-right');
  
  // 计算单个slide的总宽度(包含gap)
  const slideWidth = slides[0].offsetWidth + parseInt(getComputedStyle(slidesContainer).gap);
  const maxSlides = slides.length;
  const visibleSlides = 3; // 一行显示的slide数量
  let currentSlide = 0;
  let autoPlayInterval;

  // 启动自动轮播
  function startAutoPlay() {
    autoPlayInterval = setInterval(() => {
      moveToSlide(currentSlide + 1);
    }, 5000); // 每5秒切换一次
  }

  // 停止自动轮播
  function stopAutoPlay() {
    clearInterval(autoPlayInterval);
  }

  // 切换到指定索引的slide
  function moveToSlide(index) {
    const maxIndex = maxSlides - visibleSlides;
    currentSlide = index;
    // 边界处理:超出范围时循环
    if (currentSlide < 0) currentSlide = maxIndex;
    if (currentSlide > maxIndex) currentSlide = 0;
    slidesContainer.style.transform = `translateX(-${currentSlide * slideWidth}px)`;
  }

  // 绑定按钮点击事件
  btnRight.addEventListener('click', () => moveToSlide(currentSlide + 1));
  btnLeft.addEventListener('click', () => moveToSlide(currentSlide - 1));

  // 鼠标悬停暂停轮播,离开继续
  slidesContainer.addEventListener('mouseenter', stopAutoPlay);
  slidesContainer.addEventListener('mouseleave', startAutoPlay);

  // 初始化启动自动轮播
  startAutoPlay();
});

关键说明

  1. 布局核心:新增.slides-container包裹所有slide,外层.caraseoul设置overflow: hidden,确保仅显示可视区域内的内容。
  2. 宽度适配:通过calc计算slide宽度,保证一行固定显示3个,可修改visibleSlides值调整显示数量。
  3. 平滑动画:利用transform: translateX()实现滑动,配合transition属性添加过渡效果。
  4. 用户体验:自动轮播默认每5秒触发一次,鼠标悬停时暂停,避免干扰用户阅读。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 14:48:07