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

滚动时导航项放大及菜单高亮JS代码失效求助

问题与解决方案:滚动导航高亮+放大效果

问题说明

我想要实现滚动时导航栏菜单项放大的效果,但现有负责滚动高亮菜单的JavaScript代码完全不工作——滚动时console.log(pageXOffset)或console.log(sectionLeft)都没有输出,根本没法排查问题。

代码问题排查

  1. 滚动事件绑定错误:页面的横向滚动是在.inner-wrapper容器内,而非window全局,绑定window的scroll事件不会触发,导致console无输出。
  2. 变量未声明/使用错误:循环变量i未用let/var声明,造成全局污染;操作导航项时误用未定义的navbarItem,应该用已获取的navLi。
  3. 逻辑判断错误:判断nav项匹配时用了赋值运算符=,而非全等比较===;匹配逻辑错误,未将section的id与nav项的href对应。
  4. 元素位置计算不准确:用offsetLeft获取位置受父元素布局影响,改用getBoundingClientRect()更可靠。

修正后的完整代码

HTML

</head>
<body>
    <header>
        <nav id="navbar">
            <ul id="navbarlist">
                <li class="navbarItem home"><a href="#home">home</a></li>
                <li class="navbarItem about"><a href="#about">about</a></li>
                <li class="navbarItem products"><a href="#products">products</a></li>
                <li class="navbarItem services"><a href="#services">services</a></li>
                <li class="navbarItem contactus"><a href="#contactus">contact us</a></li>
            </ul>
        </nav>
    </header>
    <main>
        <div class="outer-wrapper">
            <div class="inner-wrapper">
                <section class="sections" id="home"></section>
                <section class="sections" id="about"></section>
                <section class="sections" id="products"></section>
                <section class="sections" id="services"></section>
                <section class="sections" id="contactus"></section>
            </div>
        </div>
    </main>
</body>
</html>

CSS

#navbar{
    position: absolute;
    width: 50vw;
    left: calc(50vw - 25vw);
}
#navbarlist{
    top: 50px;
    left: 25vw;
    width: 50vw;
    position: fixed;
    display: flex;
    justify-content: space-between;
    z-index: 1;
    padding: 0;
    list-style: none; /* 移除默认列表样式 */
}
.navbarItem{
    display: flex;
    justify-content: center;
    align-items: center;
    color: #000;
    opacity: 0.5;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    transition: all 0.3s ease; /* 添加过渡动画,让放大更平滑 */
}
.navbarItem:hover{
    transform: scale(1.5);
    margin-top: 30px;
}
.active{
    transform: scale(1.3);
    margin-top: 10px;
    color: aqua;
    opacity: 1; /* 高亮时完全不透明 */
}
.sections{
    width: 100vw;
    height: 100vh; /* 给section设置高度,方便滚动测试 */
    flex-shrink: 0; /* 防止section被压缩 */
}
/* 给不同section加背景色区分 */
#home { background: #f0f0f0; }
#about { background: #e0e0e0; }
#products { background: #d0d0d0; }
#services { background: #c0c0c0; }
#contactus { background: #b0b0b0; }

.outer-wrapper{
    width: 100vw;
    height: 100vh;
    overflow: hidden; /* 隐藏外部滚动条 */
}
.inner-wrapper{
    display: flex;
    height: 100vh;
    overflow-x: auto; /* 开启横向滚动 */
    scroll-snap-type: x mandatory; /* 可选:滚动吸附到section */
}
.sections{
    scroll-snap-align: start; /* 可选:滚动吸附对齐 */
}

JavaScript

<script>
    const sections = document.querySelectorAll('section');
    const navLi = document.getElementsByClassName('navbarItem');
    const innerWrapper = document.querySelector('.inner-wrapper');

    // 绑定容器的滚动事件,而非window
    innerWrapper.addEventListener('scroll', changeOnScroll);

    function changeOnScroll(){
        let currentId = "";
        // 获取容器的水平滚动距离
        const scrollLeft = innerWrapper.scrollLeft;
        // 获取容器的视口宽度
        const viewportWidth = innerWrapper.clientWidth;

        for(let i = 0; i < sections.length; i++){
            const section = sections[i];
            // 获取section相对于容器的位置
            const rect = section.getBoundingClientRect();
            // 当section进入视口一半以上时,标记为当前section
            if(rect.left <= viewportWidth / 2 && rect.right >= viewportWidth / 2){
                currentId = section.getAttribute('id');
                break; // 找到第一个匹配的就跳出循环
            }
        }

        // 更新导航项的高亮状态
        for(let i = 0; i < navLi.length; i++){
            const navItem = navLi[i];
            navItem.classList.remove('active');
            // 匹配nav项的href与section的id
            if(navItem.querySelector('a').getAttribute('href') === `#${currentId}`){
                navItem.classList.add('active');
            }
        }
    }

    // 初始加载时执行一次,确保默认高亮正确
    changeOnScroll();
</script>

关键修改说明

  • 滚动事件绑定:改为监听.inner-wrapper的scroll事件,确保滚动时触发函数。
  • 位置判断逻辑:用getBoundingClientRect()获取section的视口位置,判断是否进入视口中心,匹配更准确。
  • 导航匹配逻辑:通过nav项的href属性与section的id对应,避免索引错位问题。
  • 过渡动画:给.navbarItem添加transition属性,让放大/缩小效果更平滑。
  • 初始执行:页面加载时调用一次changeOnScroll(),确保默认状态正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:24:56