滚动时导航项无法添加active类的JavaScript问题排查
滚动导航激活失效的问题排查与修复
1. CSS 选择器错误
你写的 nav ul li:active 是CSS原生的点击激活伪类,只在鼠标按下元素时生效,和我们需要手动添加的 .active 类完全不是一回事。把CSS改成自定义类的样式:
nav ul li.active { background-color: blue; }
2. JavaScript 滚动判断逻辑漏洞
当前的判断条件 scrollY >= sectionTop 会导致两个问题:
- 只要滚动过section的顶部,就会把
current设为该section的id,而forEach是按顺序遍历所有section,后面的section会覆盖前面的current值,导致页面下方的section会一直被标记为激活,哪怕当前视图根本不在这个section里 - 没有考虑偏移量,比如如果有固定导航栏,section被导航栏挡住时就会触发激活,体验不好
修复后的JS代码:
const sections = document.querySelectorAll("section"); const navLi = document.querySelectorAll("nav ul li"); // 如果有固定导航栏,把这里改成导航栏的高度,比如50 const offset = 0; window.addEventListener("scroll", () => { let current = ""; sections.forEach((section) => { const sectionTop = section.offsetTop - offset; const sectionHeight = section.clientHeight; // 只有当滚动位置处于当前section的范围内时,才标记为当前激活项 if (scrollY >= sectionTop && scrollY < sectionTop + sectionHeight) { current = section.getAttribute("id"); } }); navLi.forEach((li) => { li.classList.remove("active"); if (li.classList.contains(current)) { li.classList.add("active"); } }); });
3. 可选优化:滚动事件节流
滚动事件会频繁触发,可能影响性能,给滚动事件加个节流函数:
// 节流函数:每隔delay毫秒才执行一次目标函数 function throttle(func, delay) { let timer = null; return function() { if (!timer) { timer = setTimeout(() => { func.apply(this, arguments); timer = null; }, delay); } }; } // 用节流后的函数处理滚动事件 window.addEventListener("scroll", throttle(() => { let current = ""; const offset = 0; sections.forEach((section) => { const sectionTop = section.offsetTop - offset; const sectionHeight = section.clientHeight; if (scrollY >= sectionTop && scrollY < sectionTop + sectionHeight) { current = section.getAttribute("id"); } }); navLi.forEach((li) => { li.classList.remove("active"); if (li.classList.contains(current)) { li.classList.add("active"); } }); }, 100));
内容的提问来源于stack exchange,提问作者dariocodes
相关产品推荐
相关产品推荐

