Anchor
FreeAn "on this page" navigation list that tracks scroll position with an IntersectionObserver and smooth-scrolls to a section on click. Vertical (side-rail) and horizontal (pill-row) layouts.
</>sv-anchor anchorscrollspytable of contentstocnavigationon this page
import { SvAnchorComponent } from '@styloviz/anchor';Demo & usage
Basic usage
Usage example — open the gallery for the full interactive demo.
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Horizontal pill row
example.htmlAngular
1 lines
<sv-anchor [items]="sections" orientation="horizontal" />
Custom scroll container + offset
example.htmlAngular
1 lines
<sv-anchor [items]="sections" [root]="scrollContainer()" [offset]="72" (activeIdChange)="onSectionChange($event)" />
When to use
- Job: document position — renders real hash links and reports where the reader is via `activeIdChange` (compare all seven in the “Choosing a navigation pattern” guide under Guides).
- A long docs or article page where readers benefit from a persistent "on this page" outline.
- You want the outline to highlight itself as the reader scrolls, without wiring up scroll listeners by hand.
- For a fixed set of in-page tabs that switch content rather than scroll to it, use Tabs instead.
Async states
None — this component has nothing to load, so it has no loading, empty or error state to drive.
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| itemsrequired | readonly AnchorItem[] | — | The sections to list and track, in document order. |
| root | HTMLElement | null | null | Scroll container the sections live in. `null` = the window/viewport. |
| orientation | AnchorOrientation | 'vertical' | Layout axis. |
| offset | number | 0 | Extra pixels kept between a jumped-to section and the top of the scroll container — room for a sticky header the section would otherwise land underneath. |
| offsetFrom | HTMLElement | null | null | A sticky header to measure instead of using a fixed `offset` — its current height becomes the offset, and follows it as it changes. |
| activation | AnchorActivation | 'last-passed' | Which reading of "current" to highlight: `'last-passed'` (the last heading scrolled past), `'first-visible'`, `'most-visible'`, or `'nearest-offset'` (the heading closest to the sticky-header line). |
| urlKey | string | null | null | Reflect the section being read into the URL under this key — pair it with `svHashNavLocation('section')` for `#installation`. Needs `provideSvNavLocation()` at the app root. |
| urlWriteMode | SvNavWriteMode | 'replace' | What a CLICK on a nav link does to history — `'push'` makes back return to the section the reader came from. Scrolling always replaces, whatever this says. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| activeIdChange | string | null | Emits whenever the active section changes, including on click-to-jump. |
| unresolved | SvUnresolvedValue<string> | Emitted when an item points at a section this page does not have exactly one of. `'unknown'` for no element, `'blocked'` for several with the same id. |
Customization & theming
- Vertical (bordered side-rail) or horizontal (pill-row) orientation.
- `offset` shifts the smooth-scroll landing position, e.g. to clear a sticky header.
- `root` scopes both the IntersectionObserver and the scroll-to call to a custom scrollable container instead of the window.
- `activeIdChange` emits whenever the active section changes, for syncing external UI.
Best practices
- Do: Give every linked section a stable `id` that matches the anchor item's `id` — the component resolves targets with `document.getElementById`.
- Do: Pass `root` when the page scrolls inside a custom container rather than the window, so the scrollspy observes the right viewport.
- Tip: Tune `rootMargin` behavior indirectly via `offset` when a sticky header covers the top of the viewport and sections trigger active state too late.
- Don't: Don't use it for fewer than 3–4 sections — a short page doesn't need an outline, and the scrollspy machinery is wasted.
Accessibility
- Rendered as a labelled `nav` landmark ("On this page").
- The active link is marked with `aria-current="true"`.
- Respects `prefers-reduced-motion`: falls back to an instant jump instead of a smooth scroll.
- Links are real anchors with real `href`s (`#section-id`), so they work without JavaScript and are keyboard-focusable in document order.
Feedback on Anchor
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.