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

Navbar滚动显示/隐藏与点击active类失效问题求助

解决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>

关键修改说明

  1. Navbar定位:将sticky改为fixed,设置固定宽度和高度,添加z-index确保层级最高,同时给body添加上内边距避免内容被遮挡
  2. 滚动判断修正:计算滚动位置时加上Navbar高度,使用offset().top获取section的绝对位置,避免position()的相对定位误差
  3. active类操作范围:仅针对.nav-link标签进行active类的添加/移除,排除Contact Us按钮内的链接
  4. 链接与section匹配:修正导航链接href与对应section的id,确保逻辑对应
  5. 平滑滚动优化:移除window.location.hash设置,避免触发额外滚动事件干扰active类判断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:15:37