如何实现滚动到对应H2时自动高亮侧边目录项?
解决滚动时目录项自动高亮的问题
已实现功能回顾
- 从
.post容器的H2标签生成.post_navigation下的目录项 - 目录滚动吸顶效果
- 点击目录项平滑滚动到对应H2位置
当前问题
滚动页面时,原代码会同时触发所有已滚动过的H2对应的目录标识,无法精准高亮当前阅读位置的目录项。
解决方案
1. 给H2和目录项添加唯一关联标识(替代文本匹配)
文本匹配容易出现重复标题的问题,我们给每个H2分配唯一ID,目录项通过data-target属性关联对应ID:
<div class="post"> <h2>Some title</h2> <p>texttexttext<br></p><p>texttexttext<br></p><p>texttexttext<br></p> <h2>Some title2</h2> <p>texttexttext<br></p><p>texttexttext<br></p><p>texttexttext<br></p> <h2>Some other title</h2> <p>texttexttext<br></p> <div class='post_navigation'>Navigation</div> </div> <script> jQuery( document ).ready(function() { jQuery('.post h2').each(function(index){ // 生成唯一ID var sectionId = 'section-' + (index + 1); jQuery(this).attr('id', sectionId); // 目录项存储对应H2的ID jQuery('.post_navigation').append('<div class="post_navigation_div" data-target="' + sectionId + '">' + jQuery(this).text() + '</div>'); }); }); </script>
2. 修复滚动高亮逻辑
遍历H2时,只记录当前滚动位置范围内的最后一个H2(即当前阅读的章节),再给对应目录项添加高亮:
jQuery(window).scroll(function(){ var scrollTop = jQuery(window).scrollTop(); var currentSectionId = ''; // 对应目录固定的top偏移量,让高亮时机更贴合阅读视角 var offset = 32; jQuery('.post h2').each(function(){ var sectionTop = jQuery(this).offset().top; // 当滚动位置超过H2顶部偏移量时,记录该H2的ID if (scrollTop >= sectionTop - offset) { currentSectionId = jQuery(this).attr('id'); } else { // H2从上到下排列,遇到不满足的项直接终止遍历,提升性能 return false; } }); // 移除所有高亮,给当前项添加高亮类 jQuery('.post_navigation_div').removeClass('active'); if (currentSectionId) { jQuery('.post_navigation_div[data-target="' + currentSectionId + '"]').addClass('active'); } });
3. 添加高亮样式
在CSS中定义高亮状态的样式:
.post_navigation_div.active { color: #ff4500; font-weight: 700; /* 可根据需求自定义其他样式,如下划线、背景色等 */ }
4. 优化点击滚动逻辑(配合ID关联)
用ID直接定位目标,替代文本匹配,更高效且避免重复标题问题:
jQuery('.post_navigation_div').on('click', function(){ var targetId = jQuery(this).data('target'); var targetTop = jQuery('#' + targetId).offset().top; // 考虑目录固定偏移量,让滚动后H2刚好处于目录下方 jQuery('html, body').animate({ scrollTop: targetTop - 32 }, 1000); // 点击时同步高亮当前目录项 jQuery('.post_navigation_div').removeClass('active'); jQuery(this).addClass('active'); });
5. 优化吸顶逻辑(统一偏移量)
把固定偏移量抽成变量,方便后续统一修改:
jQuery(document).ready(function(){ var navOffset = jQuery('.post_navigation').offset().top; var fixedTop = 32; jQuery(window).scroll(function(){ var scrollTop = jQuery(this).scrollTop(); if (scrollTop > navOffset) { jQuery('.post_navigation').css({'position':'fixed','top': fixedTop + 'px'}); } else { jQuery('.post_navigation').css({'position':'initial'}); } }); });
问题根源说明
原代码只要滚动过H2的位置就会触发标识,但页面H2是从上到下排列的,滚动到后续H2时,前面的H2位置仍小于滚动距离,导致多个项同时触发。通过记录最后一个符合条件的H2,就能保证只有当前阅读的章节对应的目录项被高亮。
内容的提问来源于stack exchange,提问作者Sens
相关产品推荐
相关产品推荐

