SponsorYour name here · $500/mo

Overview

Installation

Usage

Watch the blue bar in the “On this page” list move itself as the article scrolls. Click a link to jump to that section.

Scrollspy

/ IntersectionObserver · aria-current="location" /

also called scroll-linked navigation, current-section navigation, active table of contents, On this page navigation, in-page navigation, table of contents highlighting

“The contents list down the side that follows where I am in the article” is a scrollspy, also called scroll-linked or in-page navigation. The rail is a plain <nav> of fragment links (href="#section-id" pointing at real heading ids); an IntersectionObserver watches those section targets and moves aria-current="location" — plus the visible accent — to the one link for the section on screen. It looks like tabs, but it isn't: tabs swap one shared panel when you activate a tab, while a scrollspy leaves the whole document in place and only reflects where you already are. Sticky positioning is what keeps the rail beside the article; scrollspy is what changes its current item.

If you called it…

“a tab section updated by the scroll”“navigation traits”“a navigation menu composed of different size traits instead of tabs. each section colors a different traits when swiping”“text navigation progress tracer”“scroll navigation text top right.”“the contents links that highlight as you scroll”“the right side article menu that follows the section”

…you meant Scrollspy.

Anatomy — every part, named

  1. 1
    On-this-page rail<nav>

    “The little contents list down the side that follows where I am in the article” is the On-this-page rail — a labeled <nav> of same-document fragment links, usually kept in view with position: sticky.

  2. 2
    Current-section indicatoraria-current="location"

    “The colored line or bold link that jumps down the contents list as I scroll” is the current-section indicator — one link at a time carries aria-current="location" and the accent.

  3. 3
    Section anchor targetIntersectionObserver.observe()

    “The headings the side list is watching to know which one to light up” are the section anchor targets — real headings whose id values match the rail's href fragments.

Prompt — paste into your agent

Build Scrollspy (scroll-linked navigation) for this article: a labeled <nav> "On this page" rail of same-document fragment links kept beside the content with position: sticky, and an IntersectionObserver watching each section anchor target so exactly one link carries aria-current="location". Make the current-section indicator unmistakable — a high-contrast vertical accent bar plus a stronger label that move to the section in view — and use rootMargin to offset the activation zone by the sticky header height.

Debug prompt — when it misbehaves

Paste this, then describe what you’re seeing — it hands your agent the classic failure modes to rule out first.

Debug my scrollspy / On-this-page navigation (IntersectionObserver, aria-current="location", fragment links). Rule out: the highlight changing too early or too late because rootMargin does not account for the sticky header height; two or more links marked current at once because the observer callback sets state per entry instead of picking one winner from all intersecting sections; the last section never becoming current because the page cannot scroll far enough to bring it into the activation zone (pad the end of the article or fall back to a bottom-of-scroll rule); nothing highlighting at all because the observer root is the viewport while the sections scroll inside an overflow container, or because observe() ran before the sections existed; the rail links given role="tab" and aria-selected instead of aria-current, which makes screen readers announce a tab widget that does not exist; clicking a link jumping correctly but the highlight snapping back because the scroll-triggered observer overrides the clicked section. The symptom:

In code

The exact names this thing goes by in code — each row is one framework’s word for it. Use the row that matches your project (or paste it into your prompt).

Web APIIntersectionObserverwatches which section target is in view
ARIAaria-current="location"marks the ONE link for the section being read
Bootstrapbootstrap.ScrollSpythe ready-made implementation the name comes from
Bootstrapdata-bs-spy="scroll"declarative initializer, paired with data-bs-target
HTML<nav>the labeled landmark holding the On this page links
Web APIIntersectionObserver.rootMarginshifts the activation zone under a sticky header

See also

From the maker of this site48h Icons · Custom Apple app icons in 48 hours