Table of Contents
Allows you to quickly navigate the hierarchy of headings for the current page.
import { TableOfContents, tocCrawler } from '@skeletonlabs/skeleton';
Demo
How It Works
Heading IDs
Each page heading requires a unique ID that acts as the scroll target for inner-page navigation.
<h2 class="h2" id="how-it-works">How it Works</h2>
Anchor Links
Each link within the Table of Contents then points to the matching target ID as shown below. Note the use of the #
. When clicked, the browser will automatically scroll so that the targeted element is at the top of the visible screen.
<a href="#how-it-works">How It Works</a>
Settings
Automatic IDs
Set mode: generate
to enable tocCrawler
to automatically generate and set unique
IDs for all headings that are descendents of the element the action is applied to.
<div use:tocCrawler={{ mode: 'generate' }}>
See the example below. Note this will not overwrite IDs you have set manually.
<!-- Before: -->
<h2 class="h2">Title One</h2>
<h2 class="h2" id="my-custom-id">Title Two</h2>
<!-- After: -->
<h2 class="h2" id="title-one">Title One</h2>
<h2 class="h2" id="my-custom-id">Title Two</h2>
Prefixes and Suffixes
We recommend setting a custom heading (per the instruction above) if a conflict is found within your page. However, you may also hardcode a prefix
or suffix
to all generated IDs as follows:
<div use:tocCrawler={{ mode: 'generate', prefix: 'foo', suffix: 'bar' }}>
<!-- Ex: foo-title-one-bar -->
<!-- Ex: foo-title-two-bar -->
Ignore Headings
To ignore a heading in the target region, append a data-toc-ignore
attribute. The crawler will skip this.
<h2 class="h2" data-toc-ignore>Ignore Me</h2>
Invisible Headings
Use the Tailwind-provided Screen Reader .sr-only
class to append an invisible heading.
<h2 class="sr-only">Include Me!</h2>
Keyed Updates
In some situations you may want to force the crawler action to update on demand. Use the key
parameter and
pass a value that will be modified. This operates similar to Svelte's
key blocks.
const tabIndex = 0;
<div use:tocCrawler={{ key: tabIndex }}>
Active on Scroll
The tocCrawler
action can automatically select the top visible heading when you supply a
scrollTarget
element. That being the element that handles scrolling for the page. By default, this is set
to target the body
element. When using the Skeleton App Shell, designate
scrollTarget: '#page'
element as shown below. To disable this feature, set
scrollTarget: ''
.
NOTE: depending on your page layout, the page may not scroll low enough to activate the final links in the list.
<div use:tocCrawler={{ scrollTarget: '#page' }}>
Dynamic Attributes
Generating links constructed from dynamic attributes may result in unexpected behavior.
Example
<h2 class="h2">Greetings {name}</h2>
Svelte will compile this header to:
<h2 class="h2">"Greetings " "skeleton"</h2>
which means the header now has two children: "Greetings " and "skeleton".
Since the Table of Contents targets only the first child to avoid including any icons, etc., in the link, we end up with links missing parts of the text.
Solution
Using string interpolation solves the problem, by updating the code to:
<h2 class="h2">{`Greetings ${name}`}</h2>
The component will be compiled to:
<h2 class="h2">"Greetings skeleton"</h2>
Styling
Smooth Scrolling
Use Tailwind's scroll behavior styles to enable smooth scrolling on the scrollable element.
Make considerations for the Reduced Motion settings for proper accessability.
<!-- If using the App Shell: -->
<AppShell regionPage="scroll-smooth"></AppShell>
<!-- If NOT using the App Shell: -->
<body class="scroll-smooth"></body>
Scroll Margin
Use Tailwind's scroll margin styles if you need to offset for sticky headers
NOTE: not currently supported for Skeleton's App Shell.
<body class="scroll-mt-[100px]"></body>
Sticky Positioning
Use Tailwind's sticky positioning styles to keep the Table of Contents component visible while scrolling.
<TableOfContents class="sticky top-10" />