Navbar滚动显示/隐藏与点击active类失效问题求助
问题分析
现有代码存在以下核心问题:
- Navbar使用
position:sticky却通过top属性控制显示隐藏,两者定位逻辑冲突,导致滚动时显示异常 - 点击导航链接时,移除所有
a标签的active类,误操作了Contact Us按钮内的链接 - 滚动判断
active类时,使用position().top而非offset().top,且未考虑Navbar高度,导致位置计算不准确 - HTML中导航链接的
href与对应section的id不匹配(如About Us指向#heroSection但对应section是#aboutusSection) - 平滑滚动结束后设置
window.location.hash会触发额外滚动,干扰active类判断
解决方案
1. 修复Navbar滚动显示/隐藏逻辑
将#navbarSection的定位改为fixed,避免与sticky冲突,同时设置宽度和z-index确保导航栏始终在顶部且不被遮挡。
2. 修正active类切换逻辑
- 点击事件仅针对
.nav-link标签操作active类,排除其他链接 - 滚动判断时使用
offset().top获取section的绝对位置,并减去Navbar高度修正滚动偏移 - 匹配导航链接
href与section的id,确保对应关系正确 - 平滑滚动后不再设置
window.location.hash,避免触发额外滚动事件
修正后完整代码
JavaScript代码
// Navbar滚动显示/隐藏 const navbar = document.getElementById("navbarSection"); let prevScrollpos = window.pageYOffset; window.onscroll = function() { const currentScrollPos = window.pageYOffset; // 滚动向下隐藏,向上显示,同时避免顶部时隐藏 if (prevScrollpos > currentScrollPos || currentScrollPos === 0) { navbar.style.top = "0"; } else { navbar.style.top = "-70px"; } prevScrollpos = currentScrollPos; }; $(document).ready(function() { const navbarHeight = $("#navbarSection").outerHeight(); $(document).on("scroll", function() { onScroll(navbarHeight); }); // 平滑滚动与点击active切换 $('.nav-link[href^="#"]').on("click", function(e) { e.preventDefault(); $(document).off("scroll"); // 仅移除导航链接的active类 $(".nav-link").removeClass("active"); $(this).addClass("active"); const target = this.hash; const $target = $(target); $("html, body") .stop() .animate({ scrollTop: $target.offset().top - navbarHeight + 2, // 修正Navbar高度偏移 }, 500, "swing", function() { $(document).on("scroll", function() { onScroll(navbarHeight); }); } ); }); }); function onScroll(navbarHeight) { const scrollPos = $(document).scrollTop() + navbarHeight; // 加上Navbar高度修正位置 $("#navbarSection .nav-link").each(function() { const currLink = $(this); const refElement = $(currLink.attr("href")); if (refElement.length) { const sectionTop = refElement.offset().top; const sectionBottom = sectionTop + refElement.height(); if (scrollPos >= sectionTop && scrollPos < sectionBottom) { $(".nav-link").removeClass("active"); currLink.addClass("active"); } else { // 仅当不在当前section范围内时移除,避免顶部时误移除 if (!(scrollPos < sectionTop && currLink.attr("href") === "#heroSection")) { currLink.removeClass("active"); } } } }); }
CSS代码
* { margin: 0px; padding: 0px; box-sizing: border-box; font-family: 'Poppins', sans-serif !important; } #navbarSection { position: fixed !important; top: 0; left: 0; width: 100%; z-index: 999; background: white !important; transition: all .25s ease-in-out 0s !important; height: 70px; /* 明确高度,对应隐藏时的top值 */ } /* 给body添加上padding,避免内容被fixed导航栏遮挡 */ body { padding-top: 70px; } Section { margin-bottom: 150px; height: 100vh; display: flex; align-items: center; /* 给section添加背景色方便测试 */ background: #f5f5f5; } /* 区分不同section的背景色 */ #heroSection { background: #e8f4f8; } #serviceSection { background: #f8e8e8; } #workSection { background: #f0f8e8; } #aboutusSection { background: #f8f0e8; } #contactSection { background: #e8f0f8; } .blue-button { padding: 12px 24px !important; background-color: #3130F2 !important; border-radius: 37px !important; color: white !important; font-weight: 700 !important; } .blue-button:hover { background-color: #FECD00 !important; transition: all .25s ease-in-out 0s !important; } .closeButton { background-color: rgba(254, 205, 0, 0.4); border: 1px solid transparent; border-radius: 10px; } .closeButton:hover { background-color: rgba(254, 205, 0, 0.8); border: 1px solid #3130f2; border-radius: 10px; } .offcanvas-backdrop.show { opacity: 0.8; } .offcanvas-backdrop { background-color: #8E90A6; } .closeIcon { width: 40px; height: 40px; } .nav-link { padding: 0px !important; font-weight: 400; font-size: 20px !important; line-height: 40px !important; letter-spacing: 0.08em !important; } .nav-link:hover { color: #3130F2 !important; border-bottom-left-radius: 0%; border-bottom-right-radius: 0%; border-bottom: 3px solid #FECD00 !important; cursor: pointer !important; transition: all .18s ease-in-out 0s !important; } .nav-item:active a { background-color: #8E90A6 !important; } .navbar-nav .nav-link.active, .navbar-nav .show>.nav-link { color: #3130F2 !important; font-weight: 600; border-radius: 37px; border-bottom-left-radius: 0%; border-bottom-right-radius: 0%; border-bottom: 3px solid #FECD00; } .btn:hover { border-color: transparent !important; }
HTML代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <!-- google fonts --> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet" /> <!-- bootstrap 5.2.0 --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script> <title>Navbar on scroll</title> </head> <body> <div id="navbarSection"> <nav class="navbar navbar-expand-lg" aria-label="Offcanvas navbar large"> <div class="container-fluid"> <a class="navbar-brand" href="#heroSection"><img src="./Assets/logo.svg" alt="Logo" /></a> <button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasNavbar2" aria-controls="offcanvasNavbar2" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="offcanvas offcanvas-end mx-auto" tabindex="-1" id="offcanvasNavbar2" aria-labelledby="offcanvasNavbar2Label"> <div class="offcanvas-header"> <a class="navbar-brand" href="#heroSection"><img src="./Assets/logo.svg" alt="Logo" /></a> <button type="button" data-bs-dismiss="offcanvas" aria-label="Close" class="closeButton"> <img class="closeIcon" src="./Assets/cross.png" alt="Close Icon" /> </button> </div> <div class="offcanvas-body"> <ul class="navbar-nav align-items-center mx-auto mb-2 mb-lg-0"> <li class="nav-item"> <a class="nav-link active" href="#heroSection">About Us</a> </li> <li class="nav-item"> <a class="nav-link" href="#serviceSection">Services</a> </li> <li class="nav-item"> <a class="nav-link" href="#workSection">Work</a> </li> <li class="nav-item"> <a class="nav-link" href="#aboutusSection">About</a> </li> </ul> <div class="contact-us-button"> <button class="btn blue-button"> <a href="#contactSection" style="text-decoration: none; color: white">Contact Us</a> </button> </div> </div> </div> </div> </nav> </div> <section id="heroSection"> <div class="container"> <h1>About Us Section</h1> </div> </section> <section id="serviceSection"> <div class="container"> <h1>Services Section</h1> </div> </section> <section id="workSection"> <div class="container"> <h1>Work Section</h1> </div> </section> <section id="aboutusSection"> <div class="container"> <h1>About Section</h1> </div> </section> <section id="contactSection"> <div class="container"> <h1>Contact Us Section</h1> </div> </section> </body> </html>
关键修改说明
- Navbar定位:将
sticky改为fixed,设置固定宽度和高度,添加z-index确保层级最高,同时给body添加上内边距避免内容被遮挡 - 滚动判断修正:计算滚动位置时加上Navbar高度,使用
offset().top获取section的绝对位置,避免position()的相对定位误差 - active类操作范围:仅针对
.nav-link标签进行active类的添加/移除,排除Contact Us按钮内的链接 - 链接与section匹配:修正导航链接
href与对应section的id,确保逻辑对应 - 平滑滚动优化:移除
window.location.hash设置,避免触发额外滚动事件干扰active类判断
内容的提问来源于stack exchange,提问作者Alap Joshi
相关产品推荐
相关产品推荐

