54Table of contents
Where you are in a long piece. Its own module rather than a blog feature — a post, a lesson, a doc page and a training unit all need the same outline, and three copies is three places for the scroll-spy to drift.
Use it for
- Any prose over about four headings
- --inline or --float on narrow screens, where a sticky rail has nowhere to stick
Not for
- Three levels — a TOC that needs h4 is a TOC for a page that needs splitting
- Short pages: an outline of two items is longer than the shortcut it offers
- As the only navigation — it is an outline of one page, not a site map
Rail — the default
The hairline is the rail and the active item takes the 2px brand edge, the same current-item device the navbar and lesson row use.
markup
<nav class="ns-toc" aria-label="On this page">
<span class="ns-toc__title">On this page</span>
<a class="ns-toc__link" href="#0" aria-current="true">What is Apex</a>
<a class="ns-toc__link ns-toc__link--sub" href="#0">Governor limits</a>
<a class="ns-toc__link ns-toc__link--sub" href="#0">Bulkification</a>
<a class="ns-toc__link" href="#0">Testing</a>
</nav>Card, with reading progress
markup
<nav class="ns-toc ns-toc--card" aria-label="On this page" style="--ns-toc-progress:38%">
<span class="ns-toc__progress" aria-hidden="true"></span>
<span class="ns-toc__title">On this page</span>
<a class="ns-toc__link" href="#0">What is Apex</a>
<a class="ns-toc__link" href="#0" aria-current="true">Governor limits</a>
<a class="ns-toc__link" href="#0">Testing</a>
</nav>Numbered
For a procedure where the order IS the content. A CSS counter, so the numbers cannot get out of step with the list.
markup
<nav class="ns-toc ns-toc--numbered" aria-label="Steps">
<a class="ns-toc__link" href="#0">Create the sandbox</a>
<a class="ns-toc__link" href="#0" aria-current="true">Deploy metadata</a>
<a class="ns-toc__link" href="#0">Run the test suite</a>
</nav>Inline — the mobile strip
Scrolls sideways rather than wrapping: a wrapped strip changes where the article starts depending on how many headings it has.
markup
<nav class="ns-toc ns-toc--inline" aria-label="On this page">
<a class="ns-toc__link" href="#0" aria-current="true">What is Apex</a>
<a class="ns-toc__link" href="#0">Governor limits</a>
<a class="ns-toc__link" href="#0">Bulkification</a>
<a class="ns-toc__link" href="#0">Testing</a>
</nav>Collapsible
markup
<details class="ns-toc ns-toc--collapsible">
<summary>On this page<i class="ph ph-caret-down" aria-hidden="true"></i></summary>
<a class="ns-toc__link" href="#0" aria-current="true">What is Apex</a>
<a class="ns-toc__link" href="#0">Governor limits</a>
</details>Accessibility contract
- A real <nav> of real anchor links: it works with JS off, and the scroll-spy only adds [aria-current] on top
- [data-toc-from] builds the list from the article's own headings for a CMS that emits a body but no outline; a hand-authored TOC is left exactly as it is
- The progress bar is aria-hidden and never the only indicator — the marked link already says where you are