Skip to content

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).

Nothing clicked

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

Highlight Chapter 1Highlight Chapter 2Highlight Chapter 3Clear highlight

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.

Nothing clicked

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.

Not scrolled yet

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

AttributeDescriptionTypeDefault
activeCurrently highlighted href (controlled: external set/remove takes effect immediately; the scroll spy writes it back)string
affixEnable affix (sticky positioning, sticks to the scroll viewport/container)boolean
affix-offsetDistance from the scroll viewport top when affixed (px)string0
animationSmooth scroll switch (default true; false jumps instantly)stringtrue
blockScroll landing alignment: start / center / endScrollBlockstart
boundsTrigger boundary (px, default 5): extra lead for a section's top crossing the detection line, avoids highlight flickerstring5
directionLayout direction: vertical / horizontalstringvertical
durationSmooth scroll duration in ms (default 300; 0 jumps instantly)string300
get-current-anchorCustom 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
hashWhether clicking updates the URL hash (default true; false disables)stringtrue
internal-scrollableMake the anchor list itself internally scrollable (max-height + overflow-y: auto)boolean
itemsAnchor items JSON; items support children (multi-level nesting), target (e.g. _blank) and per-item targetOffsetAnchorItem[] | string[]
offsetHighlight detection offset in px: how early a section's top crosses the detection linestring0
replaceHistory control: use history.replaceState instead of pushStateboolean
scroll-containerScroll container selector or element id; when unset the viewport (window) is usedHTMLElement | string | null
sizeSize: small / medium / largestringmedium
target-offsetClick landing offset in px (avoids fixed headers); falls back to offset when unset; per-item targetOffset winsstring
variantStyle variant: default (rail + moving ink) / underline (sliding underline) / lineless (no axis) / block (filled background)stringdefault
EventDescription
oas-changeFired on highlight change (both click and scroll-driven), detail: { href, prevHref }

oas-anchor-target

AttributeDescriptionTypeDefault
idTarget marker id: synced to the inner part=target element, used by anchor items as the scroll landing target
NameDescription
defaultThe 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.

Released under the MIT OR Apache-2.0 License.