heading-links

Adds clickable anchor links to headings with auto-generated IDs and click-to-copy URL support.

Overview

Wraps a content area and adds anchor link icons to headings. Hover a heading to reveal the link icon; click it to scroll, update the URL hash, and copy the link to clipboard.

Usage

Wrap any content containing headings. By default, h2 and h3 elements are processed.

<heading-links> <h2>Getting Started</h2> <p>Content here...</p> <h3>Installation</h3> <p>More content...</p> </heading-links>

Attributes

AttributeValuesDefaultDescription
data-levelsComma-separated heading selectorsh2,h3Which heading levels to process
<!-- Only process h2 headings --> <heading-links data-levels="h2"> <h2>This gets an anchor</h2> <h3>This does not</h3> </heading-links> <!-- Process h2, h3, and h4 --> <heading-links data-levels="h2,h3,h4"> <h2>Anchor link</h2> <h3>Anchor link</h3> <h4>Anchor link</h4> </heading-links>

Auto-generated IDs

Headings without an id attribute get one generated from their text content. Existing IDs are preserved. Generated IDs are limited to 50 characters and de-duplicated automatically.

<!-- Existing IDs are preserved --> <heading-links> <h2 id="custom-id">This keeps its ID</h2> <h3>This gets an auto-generated ID</h3> </heading-links>

Events

EventDetailDescription
heading-links:navigate{ id: string, url: string }Fired when an anchor link is clicked
const el = document.querySelector('heading-links'); el.addEventListener('heading-links:navigate', (e) => { console.log('Navigated to:', e.detail.id); console.log('URL:', e.detail.url); });

Behavior

  • Anchor icons appear on heading hover or focus
  • Clicking an anchor scrolls smoothly to the heading, updates the URL hash, and copies the full URL to clipboard
  • A brief checkmark icon confirms the copy succeeded
  • A screen-reader announcement is made on successful copy
  • Headings inside <dialog> elements are skipped
  • A MutationObserver watches for dynamically added headings

Accessibility

  • Each anchor has aria-label="Link to [heading text]"
  • Headings are made focusable with tabindex="-1" for keyboard navigation to anchored sections
  • Copy confirmation uses role="status" with aria-live="polite"
  • Focus-visible styles on anchor links

Styling

The anchor uses the .heading-anchor class. It is hidden by default (opacity: 0) and revealed on hover/focus.

/* Custom anchor icon color */ heading-links .heading-anchor { color: var(--color-primary); } /* Always show anchors (instead of hover-only) */ heading-links .heading-anchor { opacity: 1; }

Related

  • <page-toc> — Table of contents generator (pairs well with heading-links)
  • data-copy — Click-to-copy attribute