为什么jQuery点击滚动时粘性导航的active类仅闪现后无法正常保留?
问题原因
- 高度计算维度不匹配:你代码里用
refElement.position().top获取的是元素相对于最近定位父元素(你代码里.inner__content设置了position: relative)的顶部偏移,而scrollPosition是整个文档的滚动高度,二者统计基准不一致,导致判断条件失效。 - 未计入粘性导航偏移:你的侧边导航设置了
position: sticky; top: 8rem,对应锚点元素滚动到距离视口顶部8rem的位置就应该匹配激活,你没有把这个偏移量计入滚动高度的判断逻辑。 - 平滑滚动冲突:你开启了
scroll-behavior: smooth,点击导航后滚动是有动画过渡的,过渡过程中scroll事件持续触发,错误的高度判断会把点击时临时加上的激活类清除,就会出现你说的闪现后消失的情况。
修复方案
- 修正高度计算逻辑:把
position().top替换为offset().top,后者是元素相对于整个文档顶部的偏移,和滚动高度统计基准一致。 - 计入导航偏移值:在滚动高度中加上侧边导航的sticky top偏移(8rem换算为128px,可根据实际情况调整)。
- 增加边界处理:滚动到页面底部时强制激活最后一个导航项,避免底部内容高度不足导致激活类丢失。
- 增加点击事件兼容:点击导航时临时解绑滚动事件,等平滑滚动结束后再重新绑定,避免过渡过程中激活类被误删。
修复后完整JS代码
$(document).ready(function () { // 导航sticky的top偏移,和css保持一致:8rem = 8*16px = 128px const NAV_STICKY_OFFSET = 128; // 绑定滚动事件 $(document).on("scroll", onScroll); // 绑定导航点击事件 $("aside a").on("click", function() { // 先设置当前点击项为激活状态 $("aside a").removeClass("clicked"); $(this).addClass("clicked"); // 临时解绑滚动事件,等平滑滚动结束后恢复,时长可根据滚动距离调整 $(document).off("scroll", onScroll); setTimeout(() => { $(document).on("scroll", onScroll); }, 500); }); }); function onScroll(event) { let scrollPosition = $(document).scrollTop() + NAV_STICKY_OFFSET; // 滚动到底部边界处理 if (scrollPosition + $(window).height() >= $(document).height()) { $("aside a").removeClass("clicked"); $("aside a:last").addClass("clicked"); return; } $("aside a").each(function () { let currentLink = $(this); let refElement = $(currentLink.attr("href")); if (!refElement.length) return; // 用offset().top获取相对于文档的偏移 const refTop = refElement.offset().top; const refBottom = refTop + refElement.height(); if (refTop <= scrollPosition && refBottom > scrollPosition) { $("aside a").removeClass("clicked"); currentLink.addClass("clicked"); } }); }
内容的提问来源于stack exchange,提问作者Millhorn
相关产品推荐
相关产品推荐

