Free table of contents generator
Paste an article as HTML or Markdown and get a nested table of contents built from its headings: once as HTML (<nav> with an ordered list) and once as a Markdown list. Every entry links to an anchor, and the generator writes a unique id for each heading so the links have somewhere to land. By default it includes H2 and H3; you can go as deep as H6. Your text is processed in the browser and is not uploaded.
Table of contents with 7 entries from 9 headings.
- At room temperature
#at-room-temperature- Bread bags
#bread-bags - Bread boxes
#bread-boxes
- Bread bags
- In the freezer
#in-the-freezer- Freezing slices
#freezing-slices - Freezing a whole loaf
#freezing-a-whole-loaf
- Freezing slices
- What to do with stale bread
#what-to-do-with-stale-bread
<nav aria-label="Table of contents">
<ol>
<li><a href="#at-room-temperature">At room temperature</a>
<ol>
<li><a href="#bread-bags">Bread bags</a></li>
<li><a href="#bread-boxes">Bread boxes</a></li>
</ol>
</li>
<li><a href="#in-the-freezer">In the freezer</a>
<ol>
<li><a href="#freezing-slices">Freezing slices</a></li>
<li><a href="#freezing-a-whole-loaf">Freezing a whole loaf</a></li>
</ol>
</li>
<li><a href="#what-to-do-with-stale-bread">What to do with stale bread</a></li>
</ol>
</nav>- [At room temperature](#at-room-temperature)
- [Bread bags](#bread-bags)
- [Bread boxes](#bread-boxes)
- [In the freezer](#in-the-freezer)
- [Freezing slices](#freezing-slices)
- [Freezing a whole loaf](#freezing-a-whole-loaf)
- [What to do with stale bread](#what-to-do-with-stale-bread)<h2 id="at-room-temperature">At room temperature</h2>
<h3 id="bread-bags">Bread bags</h3>
<h3 id="bread-boxes">Bread boxes</h3>
<h2 id="in-the-freezer">In the freezer</h2>
<h3 id="freezing-slices">Freezing slices</h3>
<h3 id="freezing-a-whole-loaf">Freezing a whole loaf</h3>
<h2 id="what-to-do-with-stale-bread">What to do with stale bread</h2>- The links only work once the headings on your page carry the same ids. Add the
idfrom the third box to each heading; the snippet keeps the heading text but not links or formatting inside it, so copy the ids across rather than replacing styled headings. - 2 headings are left out: outside the chosen levels, or empty.
- Markdown renderers create heading ids in slightly different ways. Check one link on your published page; if the anchors differ, use the HTML headings with explicit ids.
How the anchors are made
A table of contents link such as #freezing-slices only works if a heading on the page has id="freezing-slices". The generator creates each id from the heading text:
- Lowercase the text and strip accents, so "Crème brûlée" becomes
creme-brulee. - Replace every run of spaces and punctuation with one hyphen.
- If two headings would get the same id, add
-2,-3and so on, because an id may appear only once on a page.
When a heading in your HTML already has an id, it is kept, so links other pages already point at keep working. Untick "Keep ids the headings already have" to regenerate them all. In Markdown, an explicit {#custom-id} at the end of a heading line is respected in the same way.
The third output box lists your headings as HTML with their ids. Copy the id attributes onto the headings in your page. If your headings contain links or formatting, add only the attribute; do not replace the whole tag.
Choosing which levels to include
A table of contents is for navigation and can be shallower than the article's outline.
- H2 only suits short posts with a handful of sections.
- H2 and H3, the default, suits most guides: main sections with one level of detail.
- H4 and deeper is for reference pages and documentation. On an ordinary article it produces a list longer than a reader will scan.
The H1 is left out by default because it is the page title, which the reader has just seen. Tick "Include H1" for documents that use several H1s as part headings.
Nesting follows the heading levels. If a heading skips a level, say an H4 directly under an H2, it is nested one step under the heading before it, so the list stays valid. To find and fix skipped levels first, run the page through the heading structure checker.
Where to put it and how to mark it up
Place the table of contents after the introduction and before the first H2, where a reader decides whether the page has what they came for.
The HTML output wraps the list in <nav aria-label="Table of contents">. The nav element tells assistive technology that this is a navigation block, and the label lets a screen reader user tell it apart from the main menu. The list is an ordered list because the entries follow the order of the page. Hide the numbers with CSS (list-style: none) if you prefer.
Two details are worth adding in your stylesheet:
scroll-margin-topon headings, if the site has a sticky header, so a heading is not hidden under it after a jump.scroll-behavior: smoothon thehtmlelement, inside aprefers-reduced-motion: no-preferencemedia query, for animated scrolling that respects the reader's motion settings.
On a WordPress site you do not need to paste anything: the free Hydrogen SEO plugin has a Table of Contents block and shortcode that builds the list and the heading ids when the page is shown.
What a table of contents does for search
A table of contents is a set of internal links with descriptive anchor text, pointing at named sections of the same page. That gives search engines a compact summary of what the page covers, and gives them fragment URLs they can use to send a searcher to the relevant section. Google sometimes shows such section links under a result. That is its decision, and no markup guarantees it.
The benefit for readers is more certain. On a long page, people use the list to jump to the part they need, and a visitor who finds the answer stays.
Keep the entries identical to the headings they link to. A list that promises "Pricing" and lands on a heading called "Plans and billing" makes people doubt they are in the right place. When you later rename a heading, keep its old id, or links from other pages will stop landing on it. For how section links fit into a wider plan, see our guide to internal linking.
Common questions
Does a table of contents help SEO?
Indirectly. It adds descriptive links to each section, which helps search engines understand the page layout and can lead to section links under your result. It is not a ranking factor on its own. Its main value is helping readers reach the right part of a long page.
Why do the links in my table of contents not jump anywhere?
The headings on the page do not have ids that match the links. Each link ends in a fragment such as #setup, and the browser looks for an element with id="setup". Add the ids from the "Headings with ids" box to your headings and the links will work.
Which heading levels should a table of contents include?
H2 and H3 cover most articles. Add H4 and below only for long reference documents. If the list is longer than about a screen, it stops being a quick overview; cut a level.
Will Markdown heading links work on every platform?
Not always. Markdown renderers generate heading ids with slightly different rules for punctuation, accents and duplicates. The ids here follow the most common pattern, lowercase words joined by hyphens. Test one link after publishing, and if the anchors differ, use the HTML headings with explicit ids.
Can I change the generated ids?
Yes. An id can be any text without spaces, as long as it is unique on the page and the link uses the same value. Short ids make tidier URLs when someone shares a link to a section. Change both the heading id and the matching href.