page-toc

Table of contents with scroll-spy highlighting. Auto-generates from headings or enhances existing manual markup.

Overview

The <page-toc> component creates a table of contents that highlights the current section as you scroll. It supports two modes:

  • Auto-generated: Scans the page for headings and builds the ToC automatically
  • Manual markup: Enhances existing navigation with scroll-spy (progressive enhancement)

Attributes

Attribute Type Default Description
data-levels string h2,h3 Comma-separated heading levels to include
data-scope string main CSS selector for content scope to scan
data-title string On this page Title shown above the ToC

Auto-Generated Mode

When the component is empty, it automatically scans the page for headings (with IDs) and builds the table of contents.

<!-- Auto-generates ToC from page headings --> <page-toc></page-toc> <!-- With custom options --> <page-toc data-levels="h2,h3,h4" data-scope="article" data-title="Contents"> </page-toc>

Requirements

  • Headings must have id attributes (use heading-links to auto-generate)
  • Headings must be within the data-scope container (default: main)

Manual Markup Mode

For progressive enhancement, provide your own markup. The component will add scroll-spy behavior without modifying your structure.

<!-- Progressive enhancement: works without JS --> <page-toc> <details class="details" open> <summary class="summary">On this page</summary> <nav class="nav" aria-label="On this page"> <ul class="list"> <li class="item"> <a href="#overview" class="link">Overview</a> </li> <li class="item" data-level="1"> <a href="#installation" class="link">Installation</a> </li> <li class="item"> <a href="#usage" class="link">Usage</a> </li> <li class="item" data-level="1"> <a href="#examples" class="link">Examples</a> </li> </ul> </nav> </details> </page-toc>

CSS Classes

Class Purpose
.details Collapsible container
.summary ToC header/title
.nav Navigation wrapper
.list Links list
.item List item (use data-level for nesting)
.link Navigation link
.active Applied to current section link (auto-managed)

Scroll-Spy Behavior

The component uses IntersectionObserver to track which section is currently visible and highlights the corresponding link.

  • The first visible heading in the viewport is highlighted
  • Links receive the .active class and aria-current="true"
  • URL hash is updated when clicking links
  • Syncs with browser back/forward navigation

Responsive Behavior

The component adapts to different screen sizes:

Wide Screens (1024px+)

  • ToC is always visible
  • Position: sticky for sidebar placement
  • Full heading hierarchy shown

Narrow Screens

  • Collapsible disclosure pattern
  • Nested headings hidden (except active)
  • Click to expand/collapse

Sidebar Layout

Common pattern: ToC in a sidebar alongside main content.

<layout-sidebar data-layout-side="right" data-width="250px"> <article> <h1>Page Title</h1> <section id="overview"> <h2>Overview</h2> <p>Content...</p> </section> <section id="usage"> <h2>Usage</h2> <p>Content...</p> </section> </article> <aside> <page-toc data-levels="h2,h3"></page-toc> </aside> </layout-sidebar>

Events

Event Detail Description
toc-navigate { id: string } Fired when a ToC link is clicked
const toc = document.querySelector('page-toc'); toc.addEventListener('toc-navigate', (event) => { console.log('Navigated to:', event.detail.id); });

JavaScript API

Method Description
refresh() Rebuild ToC after dynamic content changes
// After dynamically adding content const toc = document.querySelector('page-toc'); toc.refresh();

Accessibility

  • Uses semantic <nav> element with aria-label
  • Active link marked with aria-current="true"
  • Keyboard accessible - tab to navigate, enter to activate
  • Focus moves to heading after navigation
  • Respects prefers-reduced-motion for scroll behavior

Styling with CSS Custom Properties

The component uses scoped styles via @scope. Override these properties for customization:

  • --color-interactive - Active link color
  • --color-text-muted - Inactive link color
  • --color-surface-raised - Hover background
  • --border-width-medium - Active link border

Best Practices

  • Use with heading-links to ensure headings have IDs
  • Keep ToC visible on wide screens for easy navigation
  • Use data-levels="h2,h3" for most documentation pages
  • Consider manual markup for static sites (better initial render)

Related Elements

  • heading-links - Auto-generates heading IDs and anchor links
  • layout-sidebar - Sidebar layout for ToC placement
  • nav - Navigation landmark element
  • details - Collapsible disclosure (used internally)