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

如何用原生JavaScript实现jQuery animate(scrollLeft)的菜单滚动效果?

原生JS实现菜单左右滚动替代jQuery animate()

我需要把以下实现菜单左右滚动的jQuery animate() 代码转换成原生JavaScript:

$(document).ready( function() {
    $('#btn-menu-nav-previous').click(function() {
        $(".menu-inner-box").animate({scrollLeft: "-=100px"});
    });
    
    $('#btn-menu-nav-next').click(function() {
        $(".menu-inner-box").animate({scrollLeft: "+=100px"});
    });
});

这段代码原本通过点击「上一页」和「下一页」按钮实现菜单列表的分页滚动。我尝试写了原生JS版本,但完全无法正常工作,代码如下:

HTML

<nav id="menu-container" class="arrow">
  <div id="btn-menu-nav-previous" style="fill: #FFF">
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
      <path d="M0 0h24v24H0z" fill="none" />
    </svg>
  </div>
  <div id="btn-menu-nav-next">
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
      <path d="M0 0h24v24H0z" fill="none" />
    </svg>
  </div>
  <div class="menu-inner-box">
    <div class="menu">
      <a class="menu-item" href="#">Menu 1</a>
      <a class="menu-item" href="#">Menu 2</a>
      <a class="menu-item" href="#">Menu 3</a>
      <a class="menu-item" href="#">Menu 4</a>
      <a class="menu-item" href="#">Menu 5</a>
      <a class="menu-item" href="#">Menu 6</a>
      <a class="menu-item" href="#">Menu 7</a>
      <a class="menu-item" href="#">Menu 8</a>
      <a class="menu-item" href="#">Menu 9</a>
      <a class="menu-item" href="#">Menu 10</a>
      <a class="menu-item last-item" href="#">Menu 11</a>
    </div>
  </div>
</nav>

CSS

nav#menu-container {
  background: #586e75;
  position: relative;
  width: 50%;
  height: 56px;
}

#btn-menu-nav-previous {
  text-align: center;
  color: white;
  cursor: pointer;
  font-size: 24px;
  position: absolute;
  left: 0px;
  padding: 9px 12px;
  background: #8f9a9d;
  fill: #FFF;
}

#btn-menu-nav-next {
  text-align: center;
  color: white;
  cursor: pointer;
  font-size: 24px;
  position: absolute;
  right: 0px;
  padding: 9px 12px;
  background: #8f9a9d;
  fill: #FFF;
}

.menu-inner-box {
  width: 100%;
  white-space: nowrap;
  margin: 0 auto;
  overflow: hidden;
  padding: 0px 54px;
  box-sizing: border-box;
}

.menu {
  padding: 0;
  margin: 0;
  list-style-type: none;
  display: block;
  text-align: center;
}

.menu-item {
  height: 100%;
  padding: 0px 25px;
  color: #fff;
  display: inline;
  margin: 0 auto;
  line-height: 57px;
  text-decoration: none;
  text-align: center;
  white-space: no-wrap;
}

.menu-item:hover {
  text-decoration: underline;
}

.last-item {
  margin-right: 50px;
}

尝试的原生JS代码

document.addEventListener("DOMContentLoaded", function() {
  var menu = document.querySelector(".menu-inner-box");
  var prev = document.getElementById("btn-menu-nav-previous");
  var next = document.getElementById("btn-menu-nav-next");
  prev.addEventListener("click", function() {
    menu.animate([{
      scrollLeft: menu.scrollLeft
    }, {
      scrollLeft: menu.scrollLeft - 100
    }], {
      duration: 500,
      fill: "forwards"
    });
  });
  next.addEventListener("click", function() {
    menu.animate([{
      scrollLeft: menu.scrollLeft
    }, {
      scrollLeft: menu.scrollLeft + 100
    }], {
      duration: 500,
      fill: "forwards"
    });
  });
});

问题原因及修复方案

你的原生JS代码无法工作的核心问题是:Element.animate() 仅创建视觉动画效果,不会真正修改元素的 scrollLeft 属性,动画结束后元素会回到初始滚动位置,因此看起来没有效果。

方案1:使用原生 scrollBy() 平滑滚动(推荐)

现代浏览器支持 scrollBy() 的 behavior: 'smooth' 参数,一行代码即可实现平滑滚动:

document.addEventListener("DOMContentLoaded", function() {
  const menu = document.querySelector(".menu-inner-box");
  const prevBtn = document.getElementById("btn-menu-nav-previous");
  const nextBtn = document.getElementById("btn-menu-nav-next");

  prevBtn.addEventListener("click", () => {
    menu.scrollBy({ left: -100, behavior: 'smooth' });
  });

  nextBtn.addEventListener("click", () => {
    menu.scrollBy({ left: 100, behavior: 'smooth' });
  });
});

方案2:手动实现动画逻辑(兼容旧浏览器)

如果需要兼容不支持平滑滚动的旧浏览器,可以通过定时器逐步修改 scrollLeft 值:

document.addEventListener("DOMContentLoaded", function() {
  const menu = document.querySelector(".menu-inner-box");
  const prevBtn = document.getElementById("btn-menu-nav-previous");
  const nextBtn = document.getElementById("btn-menu-nav-next");
  let isScrolling = false; // 防止重复触发动画

  function animateScroll(targetScrollLeft, duration = 500) {
    if (isScrolling) return;
    isScrolling = true;

    const startScrollLeft = menu.scrollLeft;
    const distance = targetScrollLeft - startScrollLeft;
    const startTime = performance.now();

    function step(currentTime) {
      const elapsed = currentTime - startTime;
      const progress = Math.min(elapsed / duration, 1);
      // 缓动函数让动画更自然
      const easeProgress = progress < 0.5 ? 2 * progress * progress : 1 - Math.pow(-2 * progress + 2, 2) / 2;
      
      menu.scrollLeft = startScrollLeft + distance * easeProgress;

      if (progress < 1) {
        requestAnimationFrame(step);
      } else {
        isScrolling = false;
      }
    }

    requestAnimationFrame(step);
  }

  prevBtn.addEventListener("click", () => {
    animateScroll(menu.scrollLeft - 100);
  });

  nextBtn.addEventListener("click", () => {
    animateScroll(menu.scrollLeft + 100);
  });
});

另外,你CSS里的 .menu-item 存在拼写错误:white-space: no-wrap 应改为 white-space: nowrap,确保菜单项保持一行显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:12:37