Founding sponsorYour name here

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 scrollnavigation traitsa navigation menu composed of different size traits instead of tabs. each section colors a different traits when swipingtext navigation progress tracerscroll navigation text top right.the contents links that highlight as you scrollthe right side article menu that follows the section

…you meant a 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

Search

Describe the UI element you're thinking of