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

如何检测滚动过同class元素并高亮对应菜单锚点?

解决滚动过元素时菜单锚点的.active类切换问题

问题分析

你的代码能成功添加.active类,但无法正确移除,核心原因是遍历每个.title元素时的逻辑冲突:每次循环都会对满足条件的锚点加active,同时对不满足的锚点移除active,导致多个元素的判断互相干扰,最终状态混乱。比如滚动到第二个.title之后,第一个.title的判断会移除active,但第二个的判断又会重新添加,甚至可能出现多个锚点同时带有active的情况。

解决方案

我们需要调整逻辑:先统一移除所有锚点的active类,再找到最后一个被完全滚动过的.title元素,给其对应的锚点添加active类。这样就能保证始终只有一个锚点处于激活状态,且会在滚动过下一个元素时自动切换。

修改后的代码

window.addEventListener("scroll", function () {
  // 获取所有标题元素和菜单链接
  const sections = document.querySelectorAll('.title');
  const menuLinks = document.querySelectorAll('.menu li a');
  
  // 先移除所有菜单链接的active类
  menuLinks.forEach(link => link.classList.remove('active'));
  
  // 从后往前遍历,找到最后一个被完全滚动过的标题
  for (let i = sections.length - 1; i >= 0; i--) {
    const section = sections[i];
    // 判断是否已完全滚动过当前标题(滚动距离超过标题的底部位置)
    if (window.scrollY > section.offsetTop + section.offsetHeight) {
      const id = section.getAttribute('id');
      const correspondingLink = document.querySelector(`.menu li a[href="#${id}"]`);
      if (correspondingLink) {
        correspondingLink.classList.add('active');
      }
      break; // 找到目标后停止遍历,提升性能
    }
  }
});

代码说明

  1. 统一移除active类:每次滚动事件触发时,先清除所有菜单锚点的active状态,避免多个锚点同时激活。
  2. 从后往前遍历标题:这样能快速定位到最后一个被完全滚动过的元素,确保激活的是当前最“新”的对应锚点。
  3. 判断滚动条件:window.scrollY > section.offsetTop + section.offsetHeight确保整个标题元素已经被滚动出视口顶部。
  4. 添加active类:找到对应锚点后添加active,并停止遍历,减少不必要的DOM操作。

补充说明

如果希望页面初始状态下第一个锚点默认激活,可以在代码初始化时给第一个菜单链接添加active类:

// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
  document.querySelector('.menu li a').classList.add('active');
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 04:42:03