How to Add Comments in Markdown
Markdown has no comment syntax, so there are two workarounds — and they hide your text to different depths. This guide covers both, which one actually keeps the text out of the published HTML, and the blank-line rule that makes comments leak onto the page.
Short answer
Use an HTML comment: <!-- your note -->. It works nearly everywhere and spans multiple lines. If the text must not appear in the generated HTML either, use an unused link label — [//]: # (your note) — with a blank line above and below it. In MDX, neither works; use {/* your note */}.
Method 1: HTML Comments
Markdown lets raw HTML through, so an HTML comment is a comment in Markdown too. This is the method to reach for by default: it is the most widely supported, it reads clearly to anyone who has written HTML, and it is the only one that spans multiple lines in a single construct.
Markdown
Visible paragraph.
<!-- This note never appears on the page. -->
Another visible paragraph.Preview
Visible paragraph.
Another visible paragraph.
Markdown
The build takes <!-- roughly --> two minutes.Preview
The build takes two minutes.
Markdown
Visible paragraph.
<!-- This note never appears on the page. -->
Another visible paragraph.HTML output
<p>Visible paragraph.</p>
<!-- This note never appears on the page. -->
<p>Another visible paragraph.</p>Method 2: The [//]: # Link-Label Trick
This one is pure Markdown, no HTML involved. A line like [//]: # (note) declares a reference link named // that the document never uses — and parsers discard unused link definitions completely. Nothing is rendered, and unlike an HTML comment nothing reaches the output either.
Markdown
Visible paragraph.
[//]: # (This note leaves no trace at all.)
Another visible paragraph.HTML output
<p>Visible paragraph.</p>
<p>Another visible paragraph.</p>The exact spelling varies between guides and all of these work. The label // is conventional because it reads like a comment in other languages and is unlikely to collide with real link text.
[//]: # (The most common form.)
[comment]: # (Any unused label works.)
[//]: <> (An empty autolink as the destination.)
[//]: # "A double-quoted title instead of parentheses."There is one genuinely surprising failure. Because the line really is a link definition, writing the same label in the text later makes the parser join them into a real link — and your private note ends up in a title attribute, visible on hover.
Markdown
[//]: # (internal note: rewrite this)
See the [//] section for details.HTML output
<p>See <a href="#" title="internal note: rewrite this">//</a> for details.</p>Commenting Out Multiple Lines
To park a whole draft section, wrap it in one HTML comment. Markdown inside <!-- --> is never parsed, so a commented-out heading does not become a heading and a commented-out list does not become a list — the entire block is skipped.
Markdown
<!--
## Draft section
This whole block is commented out, **formatting and all**.
- including
- this list
-->
Only this line renders.Preview
Only this line renders.
The link-label method has no multi-line form, so you repeat it per line. Consecutive lines are fine — they do not need blank lines between them, only around the group as a whole.
Markdown
[//]: # (First note.)
[//]: # (Second note.)
[//]: # (Third note - no blank lines needed between them.)
Visible text.Preview
Visible text.
MDX, Docusaurus, Next.js and Astro
MDX parses your document as JSX, and <!-- is not valid there. An HTML comment is not ignored, and it does not render — it fails the build outright. Use a JavaScript comment inside braces instead.
<!-- This throws: Unexpected character "!" (U+0021) -->{/* This is the only comment syntax MDX accepts. */}
<Callout>MDX content here.</Callout>.md file to .mdx: content that rendered fine for years suddenly refuses to compile with Unexpected character “!” (U+0021). The fix is a find-and-replace of every <!-- --> to {/* */}.Obsidian's Native %% Comments
Obsidian is the one popular Markdown tool that added a real comment syntax rather than leaving people to work around the gap. Wrap text in %% and it is shown in Editing view and hidden in Reading view. It works inline and across multiple lines.
%% This whole line is an Obsidian comment. %%
Text with an %%inline%% comment in the middle.
%%
A block comment
spanning several lines.
%%%% and the percent signs render as literal text. If the vault is ever published or pushed to GitHub, use HTML comments instead.Common Mistakes
Four of these five make the comment appear on the page — the failure mode is always the same, because a link label that does not parse as a link label is just a line of text.
Broken
Some text here.
[//]: # (my comment)
More text here.Fixed
Some text here.
[//]: # (my comment)
More text here.Broken
[//]: # (my comment) and then moreFixed
[//]: # (my comment)
and then moreBroken
[//]: # (see the docs (page 4) for context)Fixed
[//]: # (see the docs [page 4] for context)Broken
Some text.
[//]: # (my comment)
More text.Fixed
Some text.
[//]: # (my comment)
More text.Broken
<!-- API key for staging: sk_live_abc123 -->Fixed
<!-- Staging credentials live in the team vault. -->Quick Reference
| Syntax | Where it applies | In HTML output? |
|---|---|---|
| <!-- note --> | Almost everywhere; multi-line and inline | Usually kept |
| [//]: # (note) | CommonMark, GFM; own block only | Removed |
| [comment]: # (note) | Same - any unused label works | Removed |
| [//]: <> (note) | Same, with an empty destination | Removed |
| [//]: # "note" | Same, double-quoted title form | Removed |
| {/* note */} | MDX only - Docusaurus, Next.js, Astro | Removed |
| %% note %% | Obsidian only; inline and block | Removed |
Platform Support
Comment support tracks how much HTML a renderer allows. Document tools allow enough. Chat apps allow none, which is why there is no way to hide text in a Discord or Slack message.
| Platform | Supported? | Notes |
|---|---|---|
| GitHub / GitLab | Yes | Both methods work in READMEs, issues, PRs, and wikis. The sanitizer drops comment nodes, so they do not even reach the rendered page source - but the raw file is still public. |
| CommonMark / GFM | Yes | HTML comments pass through into the HTML output. Unused link labels are discarded entirely, which is what makes the [//]: # trick leave no trace. |
| MDX (Docusaurus, Next.js, Astro) | Partial | Only {/* comment */} works. An HTML comment is a hard build error: Unexpected character "!" (U+0021). |
| Obsidian | Yes | Has its own native %%comment%% syntax that works inline and across lines. HTML comments work too. |
| VS Code preview | Yes | Both methods behave as in CommonMark. Ctrl+/ (Cmd+/) inserts an HTML comment. |
| Jupyter / R Markdown | Yes | HTML comments are hidden in rendered notebooks and knitted output alike. |
| Jekyll / Hugo / Eleventy | Yes | Both work. Template comments ({% comment %}, {{/* */}}) strip earlier, at build time. |
| Notion | Partial | Pasted HTML comments are dropped on import. Notion's own comments are a UI feature, not syntax. |
| No | HTML is escaped, so <!-- --> shows up literally. Unused link labels are still discarded. | |
| Discord / Slack | No | No HTML and no link labels. There is no way to hide text in a message. |
Frequently Asked Questions
How do you do a comment in Markdown?
Markdown has no comment syntax of its own, so you use one of two workarounds. An HTML comment, <!-- like this -->, is the most widely supported and is what most people mean by a Markdown comment. The alternative is an unused link label: a line reading [//]: # (your note), with a blank line above and below it. Both are hidden from the rendered page.
How do I comment out multiple lines in Markdown?
Use a single HTML comment that spans the lines. Put <!-- on its own line before the block and --> on its own line after it, and everything in between is skipped, including headings, lists, and bold text. With the link-label method there is no multi-line form, so you write one [//]: # (line) per line - consecutive lines are fine and do not need blank lines between them.
What is the difference between an HTML comment and the [//]: # trick?
An HTML comment is passed through into the generated HTML in most renderers, so the text is readable in the page source even though it is invisible on screen. An unused link label is discarded by the parser and leaves no trace in the output at all. Use the HTML comment for notes to collaborators, and the link label when the text must not reach the published HTML.
Are Markdown comments really hidden?
Only from the rendered page. The comment is still in the .md file, so anyone who can read the file can read the comment - clicking Raw on GitHub is enough. Never put credentials, API keys, or anything sensitive in a Markdown comment.
Why is my Markdown comment showing up as text?
Almost always a missing blank line. The [//]: # (comment) form is a block-level construct, so it needs a blank line before and after it; if it sits directly under a paragraph it is absorbed into that paragraph and printed verbatim. The other common causes are text after the closing parenthesis, an unescaped parenthesis inside the comment, and four leading spaces, which turn the line into a code block.
Do HTML comments work in MDX?
No. MDX parses the document as JSX, where <!-- is not valid, so an HTML comment is a build error: Unexpected character "!" (U+0021). Use the JavaScript form in braces instead: {/* your comment */}. This applies to Docusaurus, Next.js MDX pages, Astro .mdx files, and anything else on the MDX pipeline.
Does Obsidian have a comment syntax?
Yes, and it is the one Markdown tool with a real native one. Wrap text in %% to comment it out: %%hidden%%. It works inline in the middle of a sentence and as a block across several lines. Obsidian comments are visible in Editing view and hidden in Reading view. HTML comments also work if you need the file to stay portable.
How do I comment out a heading or a list in Markdown?
Wrap the whole block in an HTML comment. Markdown inside <!-- --> is never parsed, so a commented-out ## heading does not become a heading and a commented-out list does not become a list - the entire block is skipped. This is the usual way to park a draft section without deleting it.
Can I put a comment inside a table or a list?
An HTML comment works inside a table cell and inside a list item. The link-label form works inside a list item and inside a blockquote, but it must still start its own block, so indent it to match the item and leave blank lines around it. Neither form works inside a fenced code block, where everything is shown as written.
Why does [comment]: # sometimes turn into a link?
Because it really is a link definition, not a comment. If the same label appears in the text later - writing [//] or [comment] in brackets somewhere - the parser matches the two and renders a real link, with your note exposed in its title attribute on hover. Pick a label you would never write in prose to avoid it.
Is there an official comment syntax in CommonMark?
No. Comments have been proposed on the CommonMark forum repeatedly and none has been adopted, which is why every method on this page is a workaround built out of some other feature. The HTML comment is the closest thing to a standard because HTML passthrough is part of the spec.
Do comments affect how AI tools read a Markdown file?
Usually not in the way people expect. A model reading the raw file - which is how coding agents read AGENTS.md, llms.txt, and README files - sees the comment text like any other line. Comments hide content from human readers of the rendered page, not from anything processing the source.