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

JS水平轮播maxScroll计算错误、滚动过渡不流畅问题修复

JavaScript水平卡片轮播问题修复

问题对应修复点

  • 右按钮提前隐藏、末尾空白问题:原maxScroll计算逻辑错误,没有基于卡片实际总宽度和可视区宽度差值计算可滚动范围,修正后滚动到最后一张卡片完全展示时才会隐藏右按钮。
  • 首屏/首个元素动画不流畅问题:初始加载阶段暂时禁用过渡动画,等DOM布局完成后再启用,避免初始定位过程触发不必要的过渡效果。

修正后完整代码

JavaScript 逻辑

document.addEventListener('DOMContentLoaded', () => {
  let currentScrollPosition = 0;
  const scrollAmount = 320;

  const sCont = document.querySelector(".card-container");
  const hScroll = document.querySelector(".horizontal-scroll");
  const btnScrollLeft = document.querySelector("#btn-scroll-left");
  const btnScrollRight = document.querySelector("#btn-scroll-right");

  btnScrollLeft.style.opacity = "0";
  // 初始禁用过渡,避免首屏动画卡顿
  sCont.style.transition = "none";

  // 计算真实最大滚动距离:卡片总宽度 - 可视区域宽度,取负值对应左偏移量
  const getMaxScroll = () => -(sCont.scrollWidth - hScroll.offsetWidth);
  let maxScroll = getMaxScroll();

  // 窗口尺寸变化时重新计算边界,避免缩放后越界
  window.addEventListener('resize', () => {
    maxScroll = getMaxScroll();
    if (currentScrollPosition < maxScroll) {
      currentScrollPosition = maxScroll;
      sCont.style.left = `${currentScrollPosition}px`;
      btnScrollRight.style.opacity = "0";
    }
  })

  function scrollHorizontally(val) {
    // 触发滚动时恢复过渡
    sCont.style.transition = "1s all ease-out";
    currentScrollPosition += val * scrollAmount;

    // 左边界校准
    if (currentScrollPosition > 0) {
      currentScrollPosition = 0;
      btnScrollLeft.style.opacity = "0";
    } else {
      btnScrollLeft.style.opacity = "1";
    }

    // 右边界校准
    if (currentScrollPosition <= maxScroll) {
      currentScrollPosition = maxScroll;
      btnScrollRight.style.opacity = "0";
    } else {
      btnScrollRight.style.opacity = "1";
    }

    sCont.style.left = `${currentScrollPosition}px`;
  }

  // 挂载到全局供HTML内onclick调用
  window.scrollHorizontally = scrollHorizontally;

  // 首屏布局完成后恢复过渡
  requestAnimationFrame(() => {
    sCont.style.transition = "1s all ease-out";
  })
})

CSS 样式修正

只需要调整原有样式中两处问题,其余样式保持不变即可:

.horizontal-scroll {
  overflow-x: hidden;
  /* 新增相对定位,作为内部绝对定位元素的定位基准 */
  position: relative;
  min-height: 220px;
}

.card-container {
  display: flex;
  justify-content: flex-start;
  align-items: center;
  flex-direction: row;
  /* 移除错误的flex-basis: 30%属性,宽度自适应内容 */
  width: max-content;
  position: absolute;
  left: 0;
  top: 10px;
  gap: 10px;
  transition: 1s all ease-out;
}

HTML 结构

原有HTML结构不需要做任何修改,直接保留即可。


关键修复说明

  • 用scrollWidth获取卡片容器的真实总宽度(包含所有子卡片、gap间距的宽度),减去外层可视区的offsetWidth得到准确的最大可滚动距离,滚到该位置时最后一张卡片刚好贴齐可视区右边缘,不会出现空白。
  • 初始阶段禁用过渡,等DOM树加载完成、布局计算结束后再通过requestAnimationFrame恢复过渡,避免浏览器初始渲染时触发不必要的位移动画,解决首屏卡顿问题。
  • 新增窗口resize监听逻辑,浏览器窗口大小变化时自动重新计算滚动边界,避免缩放后按钮状态、滚动位置异常。
  • 修正卡片容器宽度为max-content,避免原有宽度计算逻辑导致的卡片挤压、总宽度计算错误问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:12:29