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

导航栏滚动定位导致点击链接失效问题排查与解决

问题背景

开发在线餐厅菜单时遇到以下问题:

  • 顶部固定水平导航栏支持横向滚动,内容区垂直滚动,导航链接指向页面内#section元素
  • 已实现功能:内容滚动时对应导航链接高亮、内容滚动时导航项自动滚动到屏幕中央
  • 核心问题:添加导航项自动居中功能(navScroll())后,点击导航链接时滚动失效,仅滚动约10px就停止;移除该功能后点击恢复正常

相关代码

JavaScript

// 获取所有带ID的section元素
const sections = document.querySelectorAll("section[id]");

// 监听页面滚动事件
window.addEventListener("scroll", navHighlighter);

function navHighlighter() {
  // 获取当前滚动位置
  let scrollY = window.pageYOffset;

  // 遍历所有section,获取高度、顶部位置和ID
  sections.forEach(current => {
    const sectionHeight = current.offsetHeight;
    const sectionTop = (current.getBoundingClientRect().top + window.pageYOffset) - 70;
    sectionId = current.getAttribute("id");

    // 判断当前滚动位置是否在当前section范围内,添加/移除active类
    if (scrollY > sectionTop && scrollY <= sectionTop + sectionHeight) {
      theone = document.querySelector('a.menu_item[href="#' + sectionId + '"]');
      theone.classList.add('active');
    } else {
      document.querySelector('a.menu_item[href="#' + sectionId + '"]').classList.remove('active');
    }
  });
  navScroll(theone); // 这行代码会导致点击导航时滚动中断,添加preventDefault后恢复正常
}

// 将当前激活的导航项滚动到导航栏可视区域中央(也可用scrollIntoView替代)
function navScroll(item) {
  const menu = document.getElementById("menu");
  const menu_w = menu.offsetWidth;
  const item_w = item.offsetWidth;
  const item_x = item.offsetLeft;
  menu.scrollLeft = item_x - (menu_w / 2) + (item_w / 2);
}

// 添加preventDefault后功能正常
function forceScroll(sectionID) {
  event.preventDefault();
  const section = document.getElementById(sectionID);
  window.scrollTo(0, section.offsetTop);
}

CSS

.content {
  height: 500px;
  border-bottom: 1px solid black;
}

.scroll {
  white-space: nowrap;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  -ms-overflow-style: -ms-autohiding-scrollbar;
  scroll-behavior: smooth;
}

.scroll::-webkit-scrollbar {
  display: none;
}

div#menu {
  position: fixed;
  top: 0px;
  width: 100%;
  height: 50px;
  z-index: 999;
  text-align: center;
}

a.menu_item {
  display: inline-block;
  vertical-align: middle;
  text-align: center;
  height: 50px;
  background-color: #fff;
  color: #000;
}

a.menu_item.active {
  background-color: #000;
  color: #fff;
}

section {
  display: block;
}

HTML

<div id="menu" class="scroll">
  <a class="menu_item" href="#sec_1" onclick="forceScroll('sec_1')">Link 1</a>
  <a class="menu_item" href="#sec_2" onclick="forceScroll('sec_2')">Link 2</a>
  <a class="menu_item" href="#sec_3" onclick="forceScroll('sec_3')">Link 3</a>
</div>
<section id="sec_1">
  <div class="content">Some content</div>
</section>
<section id="sec_2">
  <div class="content">Some content</div>
</section>
<section id="sec_3">
  <div class="content">Some content</div>
</section>

问题排查细节

  • 不调用navScroll()时,用户滚动或点击导航链接均正常,内容滚动时对应导航项会正确添加.active类
  • 调用navScroll()后,仅用户手动滚动内容时功能正常,点击导航链接时内容滚动会被中断
  • 仅在Chrome(版本112.0.5615.49,Mac系统)中出现该问题,Safari存在滚动不流畅等小问题但非核心
  • 定位到问题根源:平滑滚动开启时,导航栏的横向平滑滚动操作会中断内容区域的垂直平滑滚动

最终解决方案

为每个导航链接添加onclick='forceScroll([section_id])'事件绑定,在forceScroll函数中通过event.preventDefault()阻止浏览器默认的锚点跳转行为,再使用window.scrollTo()命令手动控制滚动到目标区域。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 17:09:55