magnificode
css, html

scroll-target-group: highlight the section you're reading

The problem is simple and kind of annoying: you have a table of contents next to a long article, and as the reader scrolls, the link for the section they're actually looking at should be the one that lights up.

That usually turns into JavaScript. You watch headings with scroll events or IntersectionObserver, figure out which one is "current," then keep an active class on the matching link.

That's not a huge amount of code. It's just annoying as hell to get right once short sections, tall sections, sticky headers, nested scroll containers, and "why did the active link flicker right there?" show up.

The weird CSS version is scroll-target-group, paired with :target-current.

scroll-target-group: auto goes on the wrapper that contains your anchor links. It tells the browser those links belong to one group and to keep track of which linked target is current. The anchors don't become anything weird. They're still normal links pointing at real fragment IDs.

:target-current is how you style the link the browser picked. You need both parts: the property creates the group, and the pseudo-class gives CSS something to grab onto.

<nav class="toc" aria-label="Article sections">
	<ol>
		<li><a href="#overview">Overview</a></li>
		<li><a href="#setup">Setup</a></li>
		<li><a href="#deploy">Deploy</a></li>
	</ol>
</nav>

<article class="article">
	<section id="overview"><h2>Overview</h2></section>
	<section id="setup"><h2>Setup</h2></section>
	<section id="deploy"><h2>Deploy</h2></section>
</article>
.toc {
	scroll-target-group: auto;
}

.toc a:target-current {
	color: var(--accent);
}

This is the thing everyone calls "scrollspy." I kind of hate that name because it makes the problem sound more frameworky than it is. It's just a nav that knows where the reader is.

The demo below is a progressive enhancement. In a supporting browser, the current link turns green and gets a little dot. If your browser doesn't support it, the table of contents still works as a pile of regular links. You just don't get the automatic current-section highlight.

Browser support is still the catch. As I write this, it's mostly a Chromium thing; Firefox and Safari don't support it yet, and MDN still marks it experimental. The property is being worked through in CSS Overflow Level 5. Can I Use has the current support table, and Una Kravets has a good demo if you want to go deeper.

So no, I wouldn't use this as the only way to communicate where someone is on a page yet. The links and headings are the feature. The automatic highlight is just a really nice bit of CSS on top, and in supporting browsers it deletes a chunk of fussy JavaScript.

Docs pane

Current section, browser tracked

Scroll the article pane. The table of contents highlights the section in view.

This browser supports scroll-target-group. The active link below is CSS-driven.

This browser does not support scroll-target-group with :target-current yet. The links still work, but the active highlight will not track scrolling.

Overview

This little docs page has five regular fragment links. Click one and the article pane scrolls to the matching section.

In supporting browsers, the table of contents also tracks the section currently in view while you scroll.

Install

The target sections are just normal elements with IDs. There is no hidden observer, no scroll listener, and no active class getting pushed around by React.

Keyboard users can tab through the links, activate them, then focus the article pane and keep reading with normal scrolling keys.

Tokens

The table of contents wrapper opts into scroll marker grouping with scroll-target-group: auto.

After that, the browser can match each anchor to its target and expose the current one to CSS as a pseudo-class.

Motion

The marker is intentionally small: a dot, a background tint, and a little movement on the active link.

The article pane uses smooth scrolling as a nicety, then turns it off for people who prefer reduced motion.

Support Caveat

Unsupported browsers still get the useful part of the interface: semantic links that jump to real headings.

The automatic current-section highlight is the progressive enhancement, not the whole navigation system.