Introduction
Scroll-target-group reframes a familiar pattern. Every TOC widget on the web does roughly the same thing: it watches the visible section and highlights the corresponding link. That used to mean an IntersectionObserver per link, a debounce, and a lot of subtle bugs around what “currently visible” means when two sections share the viewport.
What came before
The early-2010s approach was a scroll listener and a hand-rolled binary search. The mid-2020s approach was an IntersectionObserver and a Set. Both worked but both turned tiny intent (“show me where I am”) into surprisingly verbose JS.
What scroll-target-group does
Sets up a single scrollable region as the source of truth for which member is currently focal, and lets selectors (:target-current and friends) hook into that. JS becomes optional — the browser tracks the visible target and the CSS adapts.
Implementation in this demo
This page uses a lightweight IO fallback to mark the active TOC entry, because the full :target-current selector is still rolling out. The structural setup — one container with scroll-target-group: auto, one scroll-snap-align: start per section — is the long-term shape.
Edge cases
What happens at the bottom of the scroller when the last section is shorter than the viewport? scroll-target-group resolves it by preferring the “most-visible” element in the group, with deterministic tie-breaking. No more glitching between two sections at a snap boundary.
What’s coming next
The same group concept extends to cross-document view-transitions and to scroll-driven animations. Treating a set of elements as “one logical thing” lets the browser orchestrate them as a unit.