| id | description | slug |
|---|---|---|
toc |
Customizing headings and table-of-contents in Markdown |
/markdown-features/toc |
import BrowserWindow from '@site/src/components/BrowserWindow'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';
You can use regular Markdown headings.
## Level 2 title
### Level 3 title
#### Level 4 titleEach Markdown heading will appear as a table of contents entry.
Each heading has an ID that can be automatically generated or explicitly specified. Heading IDs allow you to link to a specific document heading in Markdown or JSX:
[link](#heading-id)<Link to="#heading-id">link</Link>By default, Docusaurus will generate heading IDs for you, based on the heading text. For example, ### Hello World will have ID hello-world.
Generated IDs have some limitations:
- The ID might not look good
- You might want to change or translate the text without updating the existing ID to avoid breaking links
A special syntax lets you set an explicit heading id.
<Code language="md">{
'### Hello World {/* #my-explicit-id */}\n\n' +
'### Hello World \u007B#my-explicit-id}\n'
}</Code>
<Code language="md">{
'### Hello World <!-- #my-explicit-id -->\n\n' +
'### Hello World \u007B#my-explicit-id}\n'
}</Code>
The heading id comment must start with #, be placed at the end of the heading and will be stripped from the rendered output.
:::tip
Use the write-heading-ids CLI command to add explicit IDs to all your Markdown documents.
The --syntax option lets you choose which syntax you prefer:
- The
classicsyntax for{#headingId} - The
mdx-commentsyntax for{/* #headingId */}
:::
:::warning Avoid the classic {#id} syntax for MDX files
For MDX files, the {#id} syntax should be avoided. Since Docusaurus v3 and MDX v2, it is not valid MDX syntax anymore. It can break external tools that support MDX (IDEs and linters). It is only supported in Docusaurus for backward compatibility, thanks to the markdown.mdx1Compat.headingIds config option. The comment-based syntax should be preferred for MDX documents.
:::
:::tip Escaping heading IDs
If your heading text contains a {# sequence that you don't want to be interpreted as a custom heading ID, you can escape it with a backslash:
### Hello World \{#not-an-id}This will render the heading text as-is, including the {#not-an-id} part, instead of treating it as a custom ID.
:::
:::warning Avoid colliding IDs
Generated heading IDs will be guaranteed to be unique on each page, but if you use custom IDs, make sure each one appears exactly once on each page, or there will be two DOM elements with the same ID, which is invalid HTML semantics, and will lead to one heading being unlinkable.
:::
Each Markdown document displays a table of contents on the top-right corner. By default, this table only shows h2 and h3 headings, which should be sufficient for an overview of the page structure. In case you need to change the range of headings displayed, you can customize the minimum and maximum heading level — either per page or globally.
To set the heading level for a particular page, use the toc_min_heading_level and toc_max_heading_level front matter.
---
# Display h2 to h5 headings
toc_min_heading_level: 2
toc_max_heading_level: 5
---To set the heading level for all pages, use the themeConfig.tableOfContents option.
export default {
themeConfig: {
tableOfContents: {
// highlight-start
minHeadingLevel: 2,
maxHeadingLevel: 5,
// highlight-end
},
},
};If you've set the options globally, you can still override them locally via front matter.
:::note
The themeConfig option would apply to all TOC on the site, including inline TOC, but front matter options only affect the top-right TOC. You need to use the minHeadingLevel and maxHeadingLevel props to customize each <TOCInline /> component.
:::
It is also possible to display an inline table of contents directly inside a Markdown document, thanks to MDX.
The toc variable is available in any MDX document and contains all the headings of an MDX document. By default, only h2 and h3 headings are displayed in the TOC. You can change which heading levels are visible by setting minHeadingLevel or maxHeadingLevel for individual TOCInline components.
{/* prettier-ignore */}
import TOCInline from '@theme/TOCInline';
<TOCInline toc={toc} />import TOCInline from '@theme/TOCInline';
<BrowserWindow>
<TOCInline toc={toc} />
</BrowserWindow>
The toc global is just a list of heading items:
declare const toc: {
value: string;
id: string;
level: number;
}[];Note that the toc global is a flat array, so you can easily cut out unwanted nodes or insert extra nodes, and create a new TOC tree.
{/* prettier-ignore */}
import TOCInline from '@theme/TOCInline';
<TOCInline
// Only show h2 and h4 headings
toc={toc.filter((node) => node.level === 2 || node.level === 4)}
minHeadingLevel={2}
// Show h4 headings in addition to the default h2 and h3 headings
maxHeadingLevel={4}
/><BrowserWindow>
<TOCInline
toc={toc.filter((node) => node.level === 2 || node.level === 4)}
minHeadingLevel={2}
maxHeadingLevel={4}
/>
</BrowserWindow>
The table-of-contents is generated by parsing the Markdown source with a Remark plugin. There are known edge-cases where it generates false-positives and false-negatives.
Markdown headings within hideable areas will still show up in the TOC. For example, headings within Tabs and details will not be excluded.
Non-Markdown headings will not show up in the TOC. This can be used to your advantage to tackle the aforementioned issue.
<details>
<summary>Some details containing headings</summary>
<h2 id="#heading-id">I'm a heading that will not show up in the TOC</h2>
Some content...
</details>The ability to ergonomically insert extra headings or ignore certain headings is a work-in-progress. If this feature is important to you, please report your use-case in this issue.
:::warning
Below is just some dummy content to have more table of contents items available on the current page.
:::
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum
Lorem ipsum