Zach’s ugly mug (his face) Zach Leat­herman

Table of Contents Web Component

00 September 15, 2026
🚾Web Component@zachleat/table-of-contents

A zero-dependency web component that client renders a table of contents from the headings on the page.

0%
Versions
1 version in
1.0.0
New
Audit
-
Issues
0
PRs
0

…and another one.

This little (zero CSS) web component has two modes: progressively enhance a hierarchy of server rendered <ol> or <ul> elements (or conveniently client render them for you if they don’t exist) to highlight which are currently visible in the viewport.

I pulled this code out of the table-of-contents.webc component from the WebC Tugboat starter project for standalone use.

You can configure a selector attribute to control the scope of the headings search. My site uses main :is(h2, h3) but the default is main :is(h2, h3, h4, h5, h6).

Again, all styles for this component are application styles. There is no component CSS on this one.

Installation

npm install @zachleat/table-of-contents

Some sample headings

Heading 3a

Heading 4 (via 3a)

Heading 3b

Heading 4 (via 3b)

Heading 3c


< Older
Solar Eclipse Toggle (a dark/light mode toggle Web Component)

Zach Leatherman IndieWeb Avatar for https://zachleat.com/is a builder for the web at Font Awesome and the creator of Build Awesome (née IndieWeb Avatar for https://www.11ty.devEleventy/11ty), an award-winning open source website generator. He measures website performance with speedlify and at one point became too fixated on web fonts. He has given 89 talks in nine different countries at events like Beyond Tellerrand, Smashing Conference, Jamstack Conf, CSSConf, and The White House. Formerly part of CloudCannon, Netlify, Filament Group, NEJS CONF, and NebraskaJS. Learn more about Zach »

Shamelessly plug your related post

These are webmentions via the IndieWeb and webmention.io.

Sharing on social media?

This is what will show up when you share this post on Social Media:

How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)