滚动区块高亮特效(侧边导航联动高亮,三种样式可调)
滚动区块高亮特效:侧边导航与滚动内容联动,当前区块自动高亮,支持左侧竖条、背景填充、底部下划线三种样式实时切换,点击导航平滑跳转,零依赖自研。
效果演示(真实可交互)
🧭 滚动右侧内容:左侧导航自动高亮当前区块;点击导航可平滑跳转
01 · 简介
区块高亮(Scrollspy)是文档站、帮助中心最常见的导航形式:侧边栏列出章节,滚动时当前章节在导航中被点亮,用户永远知道自己在哪。
实现方式有两种:一是滚动时比较各区块的 offsetTop 与 scrollTop,二是用 IntersectionObserver 观察区块相交状态。本组件采用第一种,精确且兼容性好。
02 · 特性
高亮样式有三种可选:左侧竖条、背景填充、底部下划线。竖条最克制,适合密集导航;背景填充最醒目,适合浅色主题;下划线居中,适合顶栏导航。
导航项点击后平滑滚动到对应区块,并把滚动位置留出 20px 间距,避免区块标题被容器边缘遮挡。
03 · 用法
把导航的每个链接与页面区块用相同的 id 关联(`data-target` 指向区块 id),滚动时遍历区块,找到「顶部已越过视口顶部偏移」的最后一个区块即为当前区块。
这个判断只需要一次线性遍历,区块数量通常是个位数,性能没有任何压力。整页使用时把监听对象换成 window 即可。
04 · 结语
高亮导航非常适合长文档、多步骤表单、课程目录等场景。配合「回到顶部」按钮与进度条,长页面的导航体系就完整了。
本组件为粤喵自研实现,全部代码仅需一次滚动监听与一次线性遍历,轻量、无依赖,可直接嵌入任何项目。
演示区为「左侧导航 + 右侧滚动内容」的经典文档布局:滚动右侧时左侧自动高亮当前区块,点击导航平滑跳转。高亮样式可在下方实时切换。
完整代码
<nav class="sh-nav">
<a href="#sec-1" data-target="sec-1">01 简介</a>
<a href="#sec-2" data-target="sec-2">02 特性</a>
</nav>
<div class="sh-scroller" id="shScroller">
<section class="sh-sec" id="sec-1">……</section>
<section class="sh-sec" id="sec-2">……</section>
</div>
.sh-nav a.active { border-left: 3px solid #6c8cff; color: #fff; }
const scroller = document.getElementById('shScroller');
const secs = scroller.querySelectorAll('.sh-sec');
const links = nav.querySelectorAll('a');
const OFFSET = 40;
function highlight() {
let current = secs[0];
for (const sec of secs) {
if (scroller.scrollTop + OFFSET >= sec.offsetTop) current = sec;
else break;
}
links.forEach(a => a.classList.toggle('active', a.dataset.target === current.id));
}
scroller.addEventListener('scroll', highlight, { passive: true });
highlight();
核心算法:滚动时遍历区块,找到「顶部已越过视口顶部偏移 40px」的最后一个区块作为当前区块——这是最直接的 scrollspy 实现,一次线性遍历即可,区块数通常是个位数,性能无压力。点击导航则 scrollTo({ top: sec.offsetTop - 20, behavior: 'smooth' }) 平滑跳转。
参数说明
| 参数 | 位置 | 说明 |
|---|---|---|
| 高亮样式 | data-style 属性 | bar(竖条)/ bg(填充)/ under(下划线) |
| 触发偏移 | OFFSET = 40 | 区块顶部越过视口顶部多少像素算「当前」 |
| 跳转间距 | scrollTo 的 top 值 | 留 20px 防止标题贴边 |
| 区块关联 | data-target ↔ 区块 id | 一一对应,改 id 需同步 |
| 监听对象 | window / 容器元素 | 整页或局部容器滚动 |
兼容性与性能
- 滚动回调仅做线性遍历与类名切换,不触发任何布局属性写入;
{ passive: true }不阻塞滚动线程 - 高亮切换只改类名,样式由 CSS 过渡完成,浏览器按合成层处理背景与边框变化
- 区块数量少时遍历开销可忽略;即使 50 个区块,每帧也只是几十次比较,远低于一帧的预算
- 全浏览器兼容(Chrome / Safari / Firefox / Edge / iOS / Android),无需任何 polyfill 与第三方库
常见问题
Q: 用 IntersectionObserver 实现会不会更好? 两种都可行:本组件用 offsetTop 比较,逻辑直观、无观察器回收负担;区块间距大、需要「越过即切换」的精确语义时更合适。
Q: 高亮切换有延迟或跳变? 在滚动回调里直接更新类名即可实时响应;若希望平滑过渡,给导航项加上 transition(本组件已内置),高亮样式切换会自然过渡。
Q: 区块高度特别大(一屏放不下)怎么办? 增大 OFFSET(例如设为视口高度的一半),让「区块中部进入视口」时才切换,阅读长章节时导航更稳定。
Q: 可以商用吗? 可以。本组件为粤喵自研原创代码,免费商用无需署名,无任何协议限制。
许可与来源
- 许可证:自研原创 —— 粤喵自研原创,可免费用于个人与商业项目,无需署名。查看来源公示与许可清单
- 来源:粤喵团队原创自研(从效果思路到代码实现均为独立完成,未直接复制第三方代码)
- 首次发布:2026-09-01 · 最近更新:2026-09-01
- 修改日志:2026-09-01 首次发布;2026-09-13 补充许可证与来源标注、复制按钮说明与法务页入口
- 纠错:联系页面 / min@cactus.asia,2 个工作日内核实处理
常见问题
这个组件可以商用吗?
可以。本组件为粤喵自研原创,可免费用于个人和商业项目,无需署名。
浏览器兼容性如何?
支持所有现代浏览器(Chrome / Firefox / Safari / Edge 最新版本)。旧版 IE 不支持 CSS 动画相关特性。
怎么修改动画参数?
直接调整 CSS 中的 animation-duration(时长)、animation-timing-function(缓动曲线)等属性即可,代码中有注释说明。