How to Make a Collapsible Section in Markdown
Markdown has no collapsible syntax, so you borrow HTML's <details> element. This guide covers the syntax, the blank-line rule that decides whether the Markdown inside renders at all, and the native alternatives in Obsidian, Notion, and MkDocs.
Short answer
Wrap the content in <details> and put the clickable label in <summary>. Leave a blank line after the closing </summary> tag — without it the Markdown inside is printed as raw text instead of being formatted. Add open to start it expanded.
<details>
<summary>Click to expand</summary>
Hidden content goes here, and it can use **Markdown**.
</details>The <details> Syntax
There is no collapsible section in the Markdown spec, and there never has been. What every guide calls “Markdown collapsible sections” is the HTML <details> element, which works because CommonMark deliberately lets raw HTML through. It is three parts:
<details>— the container. Everything between the tags is what collapses.<summary>— the always-visible label the reader clicks. Optional, but without one the browser shows a bare “Details” triangle.- A blank line after
</summary>— the part everyone forgets. See the next section.
Markdown
<details>
<summary>Click to expand</summary>
Hidden content goes here, and it can use **Markdown**.
</details>Preview (click it)
Click to expand
Hidden content goes here, and it can use Markdown.
<details> is passed straight through by the renderer, every preview pane on this page is a working disclosure widget — click one and it opens, the same way it will on GitHub.The Blank-Line Rule
This is the reason collapsible sections go wrong, and almost nothing that ranks for this topic says it out loud. In CommonMark, an HTML block runs until the first blank line. Everything before that blank line is copied to the output untouched — so if your content is pressed up against </summary>, it is still inside the raw HTML, and the parser never sees the asterisks as bold.
Markdown
<details>
<summary>Click to expand</summary>
This line uses **Markdown**.
</details>HTML output
<details>
<summary>Click to expand</summary>
This line uses **Markdown**.
</details>Markdown
<details>
<summary>Click to expand</summary>
This line uses **Markdown**.
</details>HTML output
<details>
<summary>Click to expand</summary>
<p>This line uses <strong>Markdown</strong>.</p>
</details>Starting It Expanded
Add the open attribute to the opening tag. It is a boolean attribute — it takes no value — and the reader can still collapse the section afterwards.
Markdown
<details open>
<summary>Already expanded</summary>
The reader can still collapse this one.
</details>Preview (click it)
Already expanded
The reader can still collapse this one.
readme_renderer, whose allow-list permits the <details> and <summary> tags but allows only id as a generic attribute. So open is stripped and the section arrives collapsed. Never put the thing a reader must see behind a toggle.What You Can Put Inside
Once the blank line has ended the HTML block, the content is ordinary Markdown. Headings, lists, tables, images, links, and fenced code blocks with syntax highlighting all behave exactly as they do outside the section.
Markdown
<details>
<summary>Everything works in here</summary>
### A heading
A paragraph, a list, and a table:
- one
- two
| Column | Value |
| ------ | ----- |
| rows | fine |
</details>Preview (click it)
Everything works in here
A heading
A paragraph, a list, and a table:
- one
- two
| Column | Value |
|---|---|
| rows | fine |
Markdown
<details>
<summary>Show the install command</summary>
```bash
npm install my-package
```
</details>Preview (click it)
Show the install command
npm install my-package
Nesting Collapsible Sections
A <details> block can contain another one, as deep as you need. Each level needs its own blank lines around its body — the rule is per-block, not per-document. The usual shape is one outer toggle for a topic and an inner one per platform or per version.
Markdown
<details>
<summary>Platform notes</summary>
<details>
<summary>macOS</summary>
Requires Xcode command line tools.
</details>
<details>
<summary>Windows</summary>
Requires the Visual C++ build tools.
</details>
</details>Preview (click it)
Platform notes
macOS
Requires Xcode command line tools.
Windows
Requires the Visual C++ build tools.
Formatting the Summary Label
The <summary> line sits before the blank line, so it is still raw HTML — which means Markdown written inside it is not parsed. This surprises people who expect **Bold** to work there.
Markdown
<details>
<summary>**Bold summary**</summary>
Body text.
</details>Preview (click it)
**Bold summary**
Body text.
Markdown
<details>
<summary><b>Bold summary</b> with <code>code</code></summary>
Body text.
</details>Preview (click it)
Bold summary with code
Body text.
If you want a real Markdown heading as the label, the same blank-line rule that saved the body will save the summary: open the tag, leave a blank line, write the Markdown, leave another blank line, and close the tag. The blank line ends the HTML block long enough for the parser to process what is between.
Markdown
<details>
<summary>
### A heading as the label
</summary>
Body text.
</details>Preview (click it)
A heading as the label
Body text.
Collapsible Sections Inside a List
Numbered setup instructions with an optional troubleshooting toggle per step is one of the most useful shapes there is, and it is where the indentation trap bites. Indent the block to the list item's content column — two spaces under a bullet, three under a 1. — and never four, which turns the whole thing into a code block.
Markdown
1. Install the dependencies.
<details>
<summary>Troubleshooting</summary>
Delete `node_modules` and try again.
</details>
2. Run the build.Preview (click it)
Install the dependencies.
Troubleshooting
Delete
node_modulesand try again.Run the build.
Native Alternatives
<details> is the answer on GitHub and GitLab because those are HTML-rendering surfaces. Several other tools grew their own collapsible syntax, and where one exists it is almost always the better choice — it is styled, it nests cleanly, and it does not depend on HTML being allowed.
Obsidian: foldable callouts
Add a - after the callout type to start it collapsed, or a + to start it expanded. Wikilinks, embeds, and nested callouts all work inside.
> [!note]- Are callouts foldable?
> Yes. A minus sign collapses the callout by default.
> [!tip]+ This one starts open
> A plus sign expands it by default.Material for MkDocs: ??? admonitions
Start an admonition with ??? instead of !!! and it renders as an expandable block. Requires the pymdownx.details extension in mkdocs.yml.
??? note "Collapsed by default"
Requires the pymdownx.details extension.
???+ note "Expanded by default"
The plus sign starts it open.Notion: toggle blocks
Notion drops pasted HTML, so <details> does nothing there. Its equivalent is a toggle block: type > followed by a space, or use /toggle. Note that this is the same keystroke that makes a blockquote in standard Markdown — in Notion a quote is " plus a space.
Chat apps: spoilers, and that is all
Discord, Slack, and Reddit allow no HTML in messages, so there is no collapsible section on any of them. The nearest thing is a spoiler, which hides a run of inline text behind a click but carries no label and no block content. Slack has no equivalent at all.
Discord: Here is the answer: ||the butler did it||
Reddit: Here is the answer: >!the butler did it!<Common Mistakes
Four of these five are about where the blank lines and the indentation go. None of them produces an error message — the section just renders wrong, or swallows your document.
Broken
<details>
<summary>Notes</summary>
This is **bold**.
</details>Fixed
<details>
<summary>Notes</summary>
This is **bold**.
</details>Broken
- Step one
<details>
<summary>More</summary>
Hidden text.
</details>Fixed
- Step one
<details>
<summary>More</summary>
Hidden text.
</details>Broken
<details>
<summary>**Bold label**</summary>
Body.
</details>Fixed
<details>
<summary><b>Bold label</b></summary>
Body.
</details>Broken
<details>
<summary>Notes</summary>
Hidden text.
## The rest of your documentFixed
<details>
<summary>Notes</summary>
Hidden text.
</details>
## The rest of your documentBroken
<details open>
<summary>Read me first</summary>
Important setup notes.
</details>Fixed
<details>
<summary>Read me first</summary>
Important setup notes.
</details>Quick Reference
| Syntax | Where it applies | Starts |
|---|---|---|
| <details>...</details> | Anywhere raw HTML is allowed - GitHub, GitLab, MDX, VS Code | Closed |
| <details open> | Same, minus PyPI, which strips the attribute | Open |
| <summary>Label</summary> | The clickable label; inline HTML only, no Markdown | — |
| > [!note]- Title | Obsidian foldable callout | Closed |
| > [!note]+ Title | Obsidian foldable callout | Open |
| ??? note "Title" | MkDocs with pymdownx.details | Closed |
| ???+ note "Title" | MkDocs with pymdownx.details | Open |
| > + space | Notion toggle block (not a blockquote) | Closed |
| ||spoiler|| | Discord - inline text only, no label | Hidden |
| >!spoiler!< | Reddit - inline text only, no label | Hidden |
Platform Support
Support tracks one thing: whether the renderer allows raw HTML through. Document and repository platforms do. Chat apps do not, which is why there is no collapsible section in a Discord or Slack message and no workaround that produces one.
| Platform | Supported? | Notes |
|---|---|---|
| GitHub | Yes | READMEs, issues, PRs, discussions, wikis, and gists. <details>, <summary>, and open all survive the sanitizer. |
| GitLab | Yes | Same syntax, same behavior, in READMEs and issue/MR descriptions. |
| CommonMark / GFM | Yes | Not a Markdown feature at all - it is raw HTML passthrough, which the spec allows. Any parser with HTML enabled renders it. |
| MDX (Docusaurus, Next.js, Astro) | Yes | <details> is valid JSX, so it works as written. Docusaurus styles it to match its admonitions. Blank lines around the body are required here too. |
| Obsidian | Partial | HTML <details> renders, but Obsidian's own foldable callouts - > [!note]- - are the better fit and are searchable and linkable. |
| VS Code preview | Yes | The built-in preview allows HTML, so the disclosure widget works as it does in a browser. |
| MkDocs / Material | Partial | Raw HTML works. The idiomatic form is a ??? collapsible admonition, which needs the pymdownx.details extension. |
| PyPI | Partial | readme_renderer allows <details> and <summary>, but its allow-list has no open attribute, so the section always ships collapsed. |
| Jupyter / R Markdown | Yes | HTML passes through to the rendered notebook and to knitted HTML output. |
| Notion | Partial | Pasted HTML is not honored. Notion's native equivalent is a toggle block: type > then a space. |
| No | HTML is escaped, so the tags appear as literal text. Use a spoiler, >!like this!<, to hide a line. | |
| Discord / Slack | No | No HTML at all. Discord has ||spoilers||; Slack has nothing that hides text. |
Frequently Asked Questions
How do you make a collapsible section in Markdown?
Markdown has no collapsible syntax, so you use the HTML <details> element, which every major Markdown renderer passes through. Put a <summary> tag on the line after <details> to hold the clickable label, leave a blank line, write your Markdown, leave another blank line, and close with </details>. The blank lines are what allow the content inside to be parsed as Markdown rather than printed as raw text.
Why is my collapsible section showing **asterisks** instead of bold text?
There is no blank line after the closing </summary> tag. In CommonMark an HTML block continues until the first blank line, so everything pressed up against <summary> is still inside the raw HTML and is emitted verbatim. Adding one empty line after </summary> - and one before </details> - fixes it.
How do I make a collapsible section expanded by default?
Add the open attribute to the opening tag: <details open>. The reader can still collapse it. Note that open is not guaranteed everywhere - PyPI's README sanitizer allows the <details> tag but strips the attribute, so a section you meant to ship expanded arrives collapsed there.
Can I put code blocks, tables, and images inside a collapsible section?
Yes. Once the blank line after </summary> has ended the HTML block, the content inside is ordinary Markdown - fenced code blocks with syntax highlighting, pipe tables, images, lists, headings, and even other collapsible sections all work. This is the usual way to keep a long install log or a screenshot gallery out of the way in a README.
Can you nest collapsible sections in Markdown?
Yes. A <details> block inside another <details> block nests as deeply as you like, and each level needs its own blank lines around its body. Nesting is common for platform-specific instructions: one outer toggle for Installation, and an inner one per operating system.
How do I make the summary label bold or add a heading to it?
Markdown written inside <summary> on the same line is not parsed, because that line is still part of the raw HTML block. Use inline HTML instead - <summary><b>Bold label</b></summary>. If you need a real heading, put a blank line after the opening <summary> tag, write the Markdown, then a blank line before </summary>, which ends the HTML block long enough for the parser to see it.
Does a collapsible section work in a list item?
Yes, as long as you indent it to the list item's content column - two spaces under a bullet, three under a numbered item - and keep the blank lines. Four spaces is the trap: that is an indented code block, so the tags render as literal code instead of a toggle.
Does GitHub support collapsible sections?
Yes, everywhere GitHub renders Markdown: READMEs, issues, pull requests, discussions, wikis, and gists. GitHub's HTML sanitizer allows <details>, <summary>, and the open attribute. This is the single most common place people use them, usually to collapse long logs, changelogs, or optional setup steps.
Do collapsible sections work on Reddit, Discord, or Slack?
No. None of the three allow raw HTML in messages. Reddit escapes the tags so they show up as literal text; Discord and Slack simply have no equivalent element. The closest thing is a spoiler - ||text|| on Discord, >!text!< on Reddit - which hides a run of text behind a click but has no label and no block content.
What is the Obsidian equivalent of a collapsible section?
A foldable callout. Add a minus sign after the callout type to start it collapsed - > [!note]- Title - or a plus sign to start it expanded. Unlike raw HTML, foldable callouts are styled, nestable, and support wikilinks and embeds inside them. HTML <details> also works in Obsidian if the note has to stay portable.
What about Notion, MkDocs, and Docusaurus?
Notion ignores pasted HTML and uses its own toggle block: type > followed by a space. Material for MkDocs has collapsible admonitions - ??? note for collapsed, ???+ note for expanded - which need the pymdownx.details extension enabled. Docusaurus renders plain <details> and styles it automatically, since MDX treats it as a JSX element.
Is content inside a collapsed section still searchable and indexed?
Yes. A collapsed <details> block is present in the HTML, so browser find-in-page, GitHub's code search, and search engine crawlers all see it - it is hidden visually, not removed. Do not use a collapsible section to hide anything sensitive, and do not assume readers will click: if something must be read, leave it in the open.