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
相关产品推荐
相关产品推荐

