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

HTML/CSS实现滚动时自动激活header对应导航元素效果咨询

实现方案

方案1:纯CSS实现(优先满足HTML/CSS技术栈需求)

依赖CSS :has() 选择器与滚动相关特性,无需写JS,适合现代浏览器场景。

基础HTML结构

<header class="site-header">
  <nav>
    <a href="#home" class="nav-link">首页</a>
    <a href="#about" class="nav-link">关于我们</a>
    <!-- 可扩展其他导航项 -->
  </nav>
</header>
<main>
  <section id="home" class="section">首页内容区域</section>
  <section id="about" class="section">关于我们内容区域</section>
  <!-- 可扩展其他页面区块 -->
</main>

对应CSS代码

/* 全局滚动配置 */
html {
  scroll-timeline: --page-scroll block;
}
/* 区块基础配置,可根据业务调整高度 */
.section {
  min-height: 100vh;
  view-timeline-name: --section;
}

/* 导航默认样式 */
.nav-link {
  color: #333;
  text-decoration: none;
  padding: 8px 16px;
  transition: all 0.2s;
}

/* 核心激活逻辑 */
/* 首页区块进入视口范围时激活首页导航 */
html:has(#home:in-view()) .nav-link[href="#home"] {
  color: #1677ff;
  border-bottom: 2px solid #1677ff;
}
/* 关于我们区块进入视口范围时激活对应导航 */
html:has(#about:in-view()) .nav-link[href="#about"] {
  color: #1677ff;
  border-bottom: 2px solid #1677ff;
}

注意:该方案兼容Chrome 115+、Edge 115+、Safari 16.4+版本浏览器,如果需要兼容低版本浏览器,可以使用下面的轻量JS兜底方案。


方案2:轻量JS实现(全浏览器兼容)

仅需极少JS代码实现,性能表现稳定,适配所有主流浏览器。

新增CSS激活样式

.nav-link.active {
  color: #1677ff;
  border-bottom: 2px solid #1677ff;
}

JS逻辑代码

const navLinks = document.querySelectorAll('.nav-link');
const sections = document.querySelectorAll('.section');
// 偏移量,可根据header固定高度调整,避免激活时机错位
const offset = 80;

window.addEventListener('scroll', () => {
  let activeId = 'home';
  sections.forEach(section => {
    const sectionTop = section.offsetTop - offset;
    if (window.scrollY >= sectionTop) {
      activeId = section.id;
    }
  });
  // 切换导航激活状态
  navLinks.forEach(link => {
    link.classList.remove('active');
    if (link.getAttribute('href') === `#${activeId}`) {
      link.classList.add('active');
    }
  });
});

// 页面加载完成后主动触发一次,保证初始状态正确
window.addEventListener('load', () => {
  window.dispatchEvent(new Event('scroll'));
});

可选优化

如果页面区块数量较多,可以替换为IntersectionObserverAPI实现,滚动监听性能更好:

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const activeId = entry.target.id;
      navLinks.forEach(link => {
        link.classList.remove('active');
        if (link.getAttribute('href') === `#${activeId}`) {
          link.classList.add('active');
        }
      });
    }
  });
}, { threshold: 0.5, rootMargin: `-${offset}px 0px 0px 0px` });

sections.forEach(section => observer.observe(section));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 00:36:04