导航栏滚动定位导致点击链接失效问题排查与解决
问题背景
开发在线餐厅菜单时遇到以下问题:
- 顶部固定水平导航栏支持横向滚动,内容区垂直滚动,导航链接指向页面内
#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
相关产品推荐
相关产品推荐

