Scroll Spy
pura-scroll-spy is an "on this page" navigation for docs and long-form text: it observes sections with IntersectionObserver and moves aria-current="location" to the link matching the section in view. Use it when you have a side table of contents that should follow the scroll. It has an agent-native layer: stable data-pura-scroll-spy-* attributes reflect the active section (active, index, count) and each instance registers itself in window.__puraScrollSpy with { id, activeId, activeIndex, sections, el, activate } so an agent can read the table-of-contents state and jump to a section via activate(idOrIndex) without inspecting the Shadow DOM.
Preview
<div style="display:grid;grid-template-columns:200px 1fr;gap:32px;max-width:860px">
<pura-scroll-spy root="#conteudo" offset="16" auto-scroll label="On this page" style="position:sticky;top:16px;align-self:start">
<a href="#introducao" style="display:block;padding:6px 10px">Introduction</a>
<a href="#instalacao" style="display:block;padding:6px 10px">Installation</a>
<a href="#uso" style="display:block;padding:6px 10px">Usage</a>
<a href="#api" style="display:block;padding:6px 10px">API</a>
</pura-scroll-spy>
<div id="conteudo" style="height:320px;overflow:auto;border:1px solid var(--pura-border, #ddd);border-radius:8px;padding:16px">
<section id="introducao"><h2>Introduction</h2><p style="height:260px">Overview of the component and when to use it.</p></section>
<section id="instalacao"><h2>Installation</h2><p style="height:260px">Import the module and use the tag, with no dependencies.</p></section>
<section id="uso"><h2>Usage</h2><p style="height:260px">Place anchors with a hash href inside the slot.</p></section>
<section id="api"><h2>API</h2><p style="height:260px">Attributes, events and the activate() method.</p></section>
</div>
</div> Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
sections | string | — | CSS selector for the sections to observe. When absent, the sections are derived from the hrefs (hash) of the links in the slot. |
root | string | — | CSS selector for the scroll container. When absent, uses the viewport (root null). |
offset | number | 0 | Top offset in px that biases which section counts as current (e.g.: to account for a sticky header). It becomes the negative top of the IntersectionObserver's rootMargin. |
auto-scroll | boolean | false | When present, the active link is scrolled into view within the nav itself (respecting prefers-reduced-motion). |
label | string | On this page | Accessible label (aria-label) for the navigation landmark. |
Installation
pura is copy-paste and dependency-free. Load the whole library, or just this component.
<link rel="stylesheet" href="/pura/tokens.css">
<script type="module" src="/pura/lib/scroll-spy.js"></script> import "./pura/lib/scroll-spy.js";