长篇文章如果缺少目录,读者往往需要不断滚动查找内容,难以快速定位感兴趣的章节。
对于博客、技术文档等内容型网站,可以根据文章正文中的标题自动生成目录,并结合滚动监听实时高亮当前阅读章节,让用户始终知道自己所在的位置。
整个实现过程不依赖第三方库,只需要利用浏览器原生 API 即可完成。
一、自动提取文章标题
目录的基础是文章结构中的标题。
通常情况下,正文中的 h2 和 h3 会承担章节划分的作用,因此我们只需要获取这些标题元素:
const headings = document.querySelectorAll(
'.post-content h2, .post-content h3'
);
为了让目录链接能够准确跳转,需要为每个标题生成唯一 ID:
headings.forEach((heading, index) => {
if (!heading.id) {
heading.id = `section-${index}`;
}
});
这样,每个章节都会拥有对应的锚点,例如:
<h2 id="section-0">文章标题</h2>
目录中的链接就可以直接定位到对应位置。
二、根据标题生成目录
获取标题列表后,可以动态创建目录内容:
const toc = document.querySelector('#article-toc');
headings.forEach(heading => {
const link = document.createElement('a');
link.href = `#${heading.id}`;
link.textContent = heading.textContent;
link.className = `toc-${heading.tagName.toLowerCase()}`;
toc.appendChild(link);
});
生成后的目录结构会类似:
第一章 项目背景
1.1 技术选型
1.2 架构设计
第二章 功能实现
点击目录项后,浏览器会自动跳转到对应章节。
为了提升阅读体验,可以开启平滑滚动:
html {
scroll-behavior: smooth;
}
相比默认的瞬间跳转,平滑滚动能够让用户更清楚地感知页面位置变化。
三、监听滚动状态,高亮当前章节
仅生成目录还不够。
当用户手动滚动阅读文章时,目录也应该同步变化,突出当前正在阅读的章节。
这里可以使用浏览器原生的 IntersectionObserver 监听标题是否进入可视区域:
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (!entry.isIntersecting) return;
document.querySelectorAll('#article-toc a')
.forEach(item => item.classList.remove('active'));
const active = document.querySelector(
`#article-toc a[href="#${entry.target.id}"]`
);
active?.classList.add('active');
});
}, {
rootMargin: '-20% 0px -70% 0px'
});
headings.forEach(heading => observer.observe(heading));
当某个标题进入指定区域时:
- 移除其他目录项的高亮状态;
- 找到对应章节的目录链接;
- 添加
active样式。
例如:
#article-toc a.active {
font-weight: bold;
}
这样用户在阅读过程中,可以实时看到当前章节。
四、处理固定导航栏遮挡问题
很多博客页面顶部都会存在固定导航栏。
如果直接使用锚点跳转,浏览器可能会把标题定位到页面最顶部,而固定导航栏会覆盖标题内容。
可以通过 scroll-margin-top 调整滚动偏移:
.post-content h2,
.post-content h3 {
scroll-margin-top: 90px;
}
其中 90px 可以根据实际导航栏高度进行调整。
五、进一步优化方向
一个完整的文章目录功能,还可以继续扩展:
- 支持目录折叠展开;
- 根据
h2/h3层级生成树形结构; - 移动端自动隐藏或悬浮显示;
- 记录用户阅读位置,下次打开自动恢复;
- 结合 Markdown 渲染流程,在服务端提前生成目录。
这些优化可以根据博客规模和用户需求逐步增加。
总结
文章目录并不是简单的页面装饰,而是提升长文章可读性的重要功能。
通过 标题提取 → 自动生成锚点 → 动态创建目录 → IntersectionObserver 滚动监听 这一套流程,就可以用很少的代码实现一个轻量、高性能、无依赖的章节导航系统。
对于技术博客、知识库和文档系统而言,一个好的目录设计能够显著降低阅读成本,让用户更加高效地获取信息。

评论区 1