Anchor
Tracks the current section on scroll and highlights it automatically; clicking an anchor smooth-scrolls to the target. Supports custom scroll containers, click landing offsets, multi-level nesting, horizontal direction, affix, a moving ink bar, style variants and history control.
Basic usage
scroll-container points to a local scroll container (selector or element id): both the observation root and the click landing target use it; when unset the viewport is used.
Scroll spy (scroll-container)
Chapter 1
Section 1 content: demonstrates scroll spy and highlight tracking.
Chapter 2
When scrolled into view, the anchor highlights the current section.
Chapter 3
Click an anchor to smooth-scroll to the corresponding section.
Highlight offset and trigger boundary
offset controls the highlight detection line (how early a section's top crosses the line); bounds is an extra lead for the trigger boundary (default 5) to avoid highlight flicker.
Highlight offset (offset / bounds)
Chapter 1
offset controls the offset of the top highlight detection zone.
Chapter 2
The highlight switches earlier when a section top crosses the offset line.
Trigger boundary (bounds)
Chapter 1
A larger bounds triggers the highlight switch earlier.
Chapter 2
Default is 5px; set to 40px here so the switch point difference is visible.
Click event
Both clicking an anchor and scroll-driven highlight changes dispatch oas-change with detail: { href, prevHref }.
Click event (oas-change)
Chapter 1
Click the left anchor to see the event output.
Chapter 2
Scrolling this container also fires the event (with old and new values).
Controlled highlight
active is a controlled attribute: an external set/remove of active directly controls the currently highlighted item (the scroll spy still takes over as you scroll).
Controlled active
Chapter 1
Click a left button to set active; the anchor highlights the corresponding item immediately.
Chapter 2
When scrolling this container, the scroll spy takes over highlighting.
Chapter 3
"Clear highlight" removes active, restoring the no-highlight state.
Click landing offset and alignment
target-offset controls the distance between the target and the container top after clicking (avoids fixed headers); it falls back to offset when unset. block controls the landing alignment (start / center / end); duration controls the smooth scroll duration, while animation="false" or duration="0" jumps instantly.
Click landing (target-offset / block / duration / animation)
Chapter 1
The dashed line marks the 80px landing line: after a click Chapter 1 aligns to it.
Chapter 2
duration=500 smooth-scrolls over about 500ms.
Landing alignment (block)
Chapter 1
block="center": the target section is vertically centered in the container.
Chapter 2
Click me to see the centered landing.
Instant landing (animation)
Chapter 1
animation="false": clicking jumps to the target instantly, no smooth transition.
Chapter 2
Equivalent to duration="0".
Nesting and target markers
items supports children for multi-level nesting (indented; child items take part in scroll highlighting). <oas-anchor-target> marks scroll targets component-style (its id is synced to the inner part=target element) instead of hand-writing heading ids. internal-scrollable makes the anchor list itself internally scrollable.
Nesting (children / oas-anchor-target / internal-scrollable)
Chapter 1
Headings wrapped by oas-anchor-target serve as scroll landing targets.
1.1 Section
Child anchors are indented and take part in highlight detection.
1.2 Section
Child anchors are indented and take part in highlight detection.
1.3 Section
Child anchors are indented and take part in highlight detection.
1.4 Section
Child anchors are indented and take part in highlight detection.
1.5 Section
Child anchors are indented and take part in highlight detection.
Chapter 2
internal-scrollable: the anchor list scrolls internally when it overflows.
Horizontal direction
Horizontal (direction=horizontal)
Chapter 1
In horizontal mode the items are laid out in a row and the ink bar slides horizontally.
Chapter 2
Scroll the container to observe highlight switching.
Chapter 3
Clicking an anchor still lands on the section.
Affix
affix pins the anchor bar while scrolling (sticky positioning); affix-offset is the distance from the viewport top when affixed. This demo watches the viewport scroll.
Affix (affix / affix-offset)
Chapter 1
Scroll the page down: the left anchor bar sticks 16px below the viewport top.
Chapter 2
The highlight follows the current section as the page scrolls.
Chapter 3
Pair affix-offset with a fixed page header to clear it.
Style variants and sizes
Style variants and sizes (variant / size)
default
underline
lineless
block
size=small
size=large
History control
Clicking an anchor updates the URL hash by default (history.pushState); replace switches to replaceState; hash="false" writes nothing.
History control (hash / replace)
Chapter 1
Three anchors watch the same container: default pushState, replace via replaceState, and hash=false writes nothing.
Chapter 2
Click the first column's anchors to watch the URL hash change.
Custom highlight
get-current-anchor names a global function that receives the scroll-computed candidate href and returns the href to actually highlight; framework users can also pass a function via the getCurrentAnchor property.
Custom highlight (get-current-anchor)
Chapter 1
No matter where you scroll, the custom strategy forces Chapter 3 to be highlighted.
Chapter 2
The event detail.href also comes from the custom strategy.
Chapter 3
The actually highlighted item.
External links
Setting target (e.g. _blank) on an item leaves the default behavior to the browser (with rel="noopener noreferrer" added automatically) and excludes it from scrolling/highlighting.
External links (item target)
API
oas-anchor
| Attribute | Description | Type | Default |
|---|---|---|---|
active | Currently highlighted href (controlled: external set/remove takes effect immediately; the scroll spy writes it back) | string | — |
affix | Enable affix (sticky positioning, sticks to the scroll viewport/container) | boolean | — |
affix-offset | Distance from the scroll viewport top when affixed (px) | string | 0 |
animation | Smooth scroll switch (default true; false jumps instantly) | string | true |
block | Scroll landing alignment: start / center / end | ScrollBlock | start |
bounds | Trigger boundary (px, default 5): extra lead for a section's top crossing the detection line, avoids highlight flicker | string | 5 |
direction | Layout direction: vertical / horizontal | string | vertical |
duration | Smooth scroll duration in ms (default 300; 0 jumps instantly) | string | 300 |
get-current-anchor | Custom highlight strategy: attribute names a global function that receives the computed candidate href and returns the actual href to highlight; the getCurrentAnchor property also accepts a function | ((activeHref: string) => string) | null | — |
hash | Whether clicking updates the URL hash (default true; false disables) | string | true |
internal-scrollable | Make the anchor list itself internally scrollable (max-height + overflow-y: auto) | boolean | — |
items | Anchor items JSON; items support children (multi-level nesting), target (e.g. _blank) and per-item targetOffset | AnchorItem[] | string | [] |
offset | Highlight detection offset in px: how early a section's top crosses the detection line | string | 0 |
replace | History control: use history.replaceState instead of pushState | boolean | — |
scroll-container | Scroll container selector or element id; when unset the viewport (window) is used | HTMLElement | string | null | — |
size | Size: small / medium / large | string | medium |
target-offset | Click landing offset in px (avoids fixed headers); falls back to offset when unset; per-item targetOffset wins | string | — |
variant | Style variant: default (rail + moving ink) / underline (sliding underline) / lineless (no axis) / block (filled background) | string | default |
| Event | Description |
|---|---|
oas-change | Fired on highlight change (both click and scroll-driven), detail: { href, prevHref } |
oas-anchor-target
| Attribute | Description | Type | Default |
|---|---|---|---|
id | Target marker id: synced to the inner part=target element, used by anchor items as the scroll landing target | — | — |
| Name | Description |
|---|---|
| default | The marked target content (e.g. multi-level headings) |
Scroll spy based on the scroll container (viewport by default); clicking smooth-scrolls to the target; nav + aria-label="Anchor navigation", the current item has aria-current="true".
A target marker component: wraps real multi-level headings and serves as the scroll landing target for anchor items; the default slot carries the marked content.