Quick Answer
Markdown is a plain-text way to format writing using ordinary punctuation, so a hash makes a heading and asterisks make bold. You can learn the useful parts in twenty minutes. The catch is that Markdown is a family of languages, not one, and knowing which flavour you write saves real frustration.
Markdown lets you format text using punctuation you already type. A hash before a line makes it a heading. Asterisks around a word make it bold. A hyphen at the start of a line makes a bullet. The file stays readable as plain text either way, which is the whole point.
You can learn the useful ninety percent in about twenty minutes, and this guide is not going to spend those twenty minutes listing syntax. Our Markdown cheatsheet already does that, with an example for every symbol. What this guide covers is the part that actually causes trouble: Markdown is not one language, and nobody tells you that until your carefully formatted table renders as a row of pipes and dashes.
What is Markdown and why does it exist?
John Gruber released Markdown in December 2004 with a simple goal. Formatted text should be readable as-is, before anything converts it. Compare a link in HTML with a link in Markdown and the argument makes itself. One is a tag wrapped around text. The other reads like a sentence with a footnote.
That readability is why Markdown spread into places HTML never would. README files, chat apps, note-taking tools, static site generators, documentation systems, and the box you are typing an issue into right now. It survives being emailed, pasted, diffed in version control and read on a terminal, because underneath it is just text.
It is formal enough to have a registered media type. RFC 7763, published by the IETF in March 2016 and authored by Sean Leonard, registered text/markdown so Markdown documents can be identified properly as they move around the internet. The RFC requires a charset parameter with no default and offers an optional variant parameter.
That variant parameter is the tell. A format that needs to declare which version of itself you wrote is a format with a problem.
Why does the same Markdown render differently everywhere?
Because the original spec was ambiguous, and everyone who implemented it made their own decisions about the gaps.
RFC 7763 does not describe Markdown as a language. It describes it as a family of related plain-text formatting syntaxes. The RFC went as far as creating an IANA registry for variant identifiers, so a document can say which dialect it was written in. Three names are reserved and cannot be registered by anyone: Standard, Common and Markdown. Gruber's original gets special status, and implementations that process the variant parameter must recognise it.
That registry is not a theoretical gesture either. Its companion document, RFC 7764, published the same month by the same author, actually populated it with eight registered variants: MultiMarkdown, GFM, pandoc, Fountain, CommonMark, kramdown-rfc2629, rfc7328 and Extra. Some of those you will recognise. Others make the point better than any argument: Fountain is a Markdown variant for writing screenplays, and kramdown-rfc2629 exists so people can draft IETF documents in Markdown.
Eight formally registered dialects, in a standards document, for a format most people describe as "just Markdown." If you have ever wondered why your formatting travels badly, that list is the reason in one line.
The CommonMark specification, written by John MacFarlane and now at version 0.31.2 dated 28 January 2024, is blunter. It states that Gruber's canonical description of Markdown's syntax does not specify the syntax unambiguously, and then lists 14 numbered examples of exactly where it falls apart.
And it does not stop at prose. CommonMark ships with 652 worked examples, each pairing a Markdown input with the exact HTML a conforming parser has to produce, and the spec is explicit that they are intended to double as conformance tests. That is the thing that turns a description into a specification, and it is precisely what Gruber's original never had. It is also worth noticing that after more than a decade of work the version number still starts with a zero. Nobody has called it 1.0 yet, which tells you how stubborn the corner cases turned out to be.
Those examples are not edge cases. They include how many spaces a sublist needs to indent, whether a blank line is required before a block quote or heading, when a list item gets wrapped in paragraph tags, which inline marker wins when two overlap, and whether a list item can contain a heading at all. Ordinary formatting, undefined.
The consequence is stated plainly in the spec: implementations have diverged considerably, so the same document renders one way on a GitHub wiki and differently when pandoc converts it to docbook. Early implementers tried resolving disputes by checking the original Perl script, but as the spec notes, Markdown.pl was quite buggy and gave manifestly bad results in many cases, so it was not a satisfactory replacement for a spec.
So when your formatting breaks after pasting it somewhere new, you are not doing it wrong. You have moved between two members of a family who disagree.
Which flavour are you actually writing?
Three matter in practice.
- Original Markdown, Gruber's 2004 version. Headings, emphasis, lists, links, images, code, blockquotes. No tables. Rarely what you are actually using today, but it is the common ancestor.
- CommonMark, the strict specification that resolves the ambiguities. If a tool says it is CommonMark compliant, its output is predictable. Still no tables, because tables were never in the base syntax.
- GitHub Flavored Markdown, CommonMark plus the extras most people assume are standard: tables, strikethrough, task list checkboxes and automatic linking of bare URLs. This is what GitHub, GitLab and a large share of documentation tools use.
Here is the practical rule. If you write a table and it renders as literal pipes and dashes, you are in a CommonMark or original-Markdown environment and tables are simply not supported there. Nothing is broken. The feature was never in that dialect.
Check what your platform documents before assuming. Most tools say which flavour they use somewhere in their help pages, and the ones that do not are usually GitHub Flavored.
Why do those note boxes only work on GitHub?
You have seen them in READMEs. A tinted panel with an icon and the word Note or Warning, sitting where a plain quote would be. They are called alerts, and they are the cleanest example in this whole guide of what writing to a flavour actually costs you.
The syntax is a blockquote with a marker on its own first line.
> [!NOTE]
> Useful information a reader should know.
> [!WARNING]
> Something that needs immediate attention.
There are five markers: NOTE, TIP, IMPORTANT, WARNING and CAUTION. On GitHub each one renders as a styled panel with its own icon. Anywhere that does not implement them, you get an ordinary blockquote with the literal text [!NOTE] sitting inside it as the first line. Nothing errors. It just looks like you left a typo in your README.
Here is the part that sharpens the point this guide has been making. Alerts are not in the GFM spec either. That formal document is version 0.29-gfm dated 6 April 2019, and it specifies five extensions: tables, task list items, strikethrough, autolinks and Disallowed Raw HTML. Alerts are not among them. GitHub documents them in its own product docs instead, calling them a Markdown extension based on the blockquote syntax.
So GitHub Flavored Markdown now means two different things depending on who is saying it. There is the frozen 2019 spec that other tools implemented, and there is whatever github.com renders this week, which has kept moving. A parser can be fully GFM compliant and still not know what an alert is, because compliance was measured against a document that predates them by years. Being a strict superset of CommonMark does not make a flavour a fixed target.
Two constraints from GitHub worth knowing before you lean on them. Alerts cannot be nested inside other elements, so an alert inside a list item or a table is not going to work. And GitHub's own guidance is to use them only where they are genuinely important, keeping to one or two per page and not stacking them back to back, which is sensible advice for the same reason that a page of highlighted text highlights nothing.
The practical rule follows the same shape as the rest of this guide. If the file lives on GitHub and only on GitHub, use them, they are good. But if that README also gets published to a package page, pulled into a docs site, or rendered by a static site generator, check what those do with it first. And when you are not sure, a bold Note: at the start of a normal paragraph carries the same meaning and survives every renderer there is.
What is that block of dashes at the top of the file?
Front matter, and the thing to understand about it is that it isn't Markdown at all. If you've opened a file from a static site generator or an Obsidian vault and found something like this sitting above the actual content, that's what you're looking at:
---
title: How to Repot a Fern
date: 2026-08-17
tags: [plants, indoor]
draft: false
---
# How to Repot a Fern
Ferns hate being moved. Here is how to do it anyway.
Everything between the two lines of three dashes is metadata. It's usually YAML, and it exists because the tool processing your file needs to know things the prose can't tell it: what to put in the page title tag, when to sort this post, which tags to file it under, whether to publish it at all.
Why isn't it part of Markdown? Because Markdown never had a way to carry metadata. RFC 7764, the IETF's guidance document on Markdown, says exactly that: the original specification provides no means to include metadata in the content stream, so it has to be supplied by supplementary means. Different communities then invented their own answers. The RFC names several, including MultiMarkdown's metadata scheme, Pandoc's title block, and the YAML front matter used by kramdown-rfc2629. Nobody agreed, so several conventions survive.
Which produces the failure people actually hit. Paste a file with front matter into a renderer that doesn't understand it and you'll see the dashes and the YAML printed as content, usually with the first line rendered as a heading because --- underneath text means a heading in Markdown. The file isn't broken. The reader just doesn't speak that convention.
Three practical points:
- The keys are set by your tool, not by a standard. Hugo, Jekyll, Astro and Obsidian each expect their own field names. Check your generator's documentation rather than copying a block from a different ecosystem.
- Delimiters vary. Three dashes is the common form, but some tools use
+++for TOML or;;;for JSON. Match what your tool expects. - Strip it before pasting elsewhere. Moving a post into a CMS, a chat message or an email means the front matter is noise. Delete those lines rather than hoping the destination hides them.
If you never use a static site generator or a notes app that indexes your files, you can ignore all of this. Front matter is a tooling convention, not something you need in order to write Markdown.
How much Markdown do you actually need to learn?
Six things. Genuinely.
- Hash for headings. One hash is the biggest, six is the smallest.
- Asterisks for emphasis. One either side for italic, two for bold.
- Hyphen for bullets. A number and a dot for ordered lists.
- Square brackets then parentheses for links. Text in the brackets, URL in the parentheses.
- Backticks for code. One for inline, three on their own line to open and close a block.
- A blank line between paragraphs. The one people miss, and the cause of more mangled output than everything else combined.
That covers almost everything most people write. Tables, footnotes and task lists are worth learning when you need them, and the cheatsheet has each one with an example. But you can be productive today with the six above.
If you want to see the rendered output while you type, our free Markdown editor shows both panes side by side and runs entirely in your browser.
When should you use HTML instead?
When you need something Markdown deliberately does not do.
Markdown was designed to cover common formatting and stop. It has no concept of classes, IDs, inline styles, nested layout, cells spanning columns, or image dimensions. That restraint is a feature, since it is what keeps the source readable, but it means there is a ceiling.
Reach for HTML when you need:
- An attribute on an element, such as a class, an ID, or a target on a link
- A table cell spanning multiple columns or rows
- A specific image width or alignment
- Anything nested in a way Markdown's indentation rules cannot express
- A form, an embed, or anything interactive
Most processors let you drop raw HTML straight into a Markdown document and it passes through untouched. Two caveats. Some platforms sanitise HTML out for security, so what works in your local editor may vanish on a comment form. And Markdown syntax generally stops working inside an HTML block, so do not expect asterisks to bold anything once you are inside a div.
Google's own style guide is less prescriptive than most advice
Worth knowing that one of the largest publishers of developer documentation on the planet does not take a hard line here at all. Google's developer documentation style guide says simply: use either HTML or Markdown.
Its reasoning gives both sides their due. Markdown is easier to write than HTML, and easier for most humans to read in source form. HTML is more expressive, particularly around semantic tagging, and can achieve effects that are difficult or impossible in Markdown. Their conclusion is that the choice is primarily a matter of personal preference, with one practical rider attached: go with whatever your team or your document template already uses.
That rider is the part worth keeping. A repo where half the docs are Markdown and half are HTML costs more in friction than either format costs on its own. So the honest version of the list above is not "switch to HTML the moment you hit these limits." It is "switch when you hit these limits, unless your team already settled the question, in which case go with them and work around the ceiling."
MDN is what "already settled it" looks like
Google leaves the choice open. MDN Web Docs went the other way and wrote the rule down, which is worth borrowing if you are trying to settle it for your own repo.
Their writing guidelines state that the baseline for MDN Markdown is GitHub Flavored Markdown, which is itself a superset of CommonMark, and that anything they do not specify falls back to the GFM spec. So they named a flavour instead of leaving it to whatever the renderer happened to do. That alone puts them ahead of most projects, and it is the practical version of everything in the flavours section above.
Then they added to it and cut from it. Extensions for definition lists, and for code blocks tagged as good or bad examples. Plus an explicit rule for when HTML wins: use it when GFM cannot express the table you need, meaning header columns, cells spanning rows or columns, or block elements inside a cell. There is even a width threshold. If the GFM version of a table would run wider than 150 characters, they switch to HTML, because past that point the source has stopped being readable and readable source was the whole reason to use Markdown.
Their summary is the cleanest statement of this rule anywhere. Authors should use the GFM syntax when they can, and fall back to raw HTML when they have to or when HTML is more readable. Read the second half again. Not only when Markdown cannot do the job, but when the Markdown version would be worse to read. That is a judgement call rather than a checklist, and it is the right one to hand your writers.
Can you put diagrams and maths in Markdown?
On some platforms, yes, and the catch is the same one running through this whole article. Neither is Markdown. Both are extensions layered on top by particular renderers, so what works in one place may print as raw text in another.
This is a well-worn path rather than a novelty. RFC 7764 explains that variants keep appearing because new communities pick Markdown up and adapt it, and it names mathematical formulae as one of the specific drivers, alongside scholarly writing and screenplays. Maths in Markdown is the standard example of a community bolting on what it needed.
Maths is usually written in LaTeX syntax, inline between dollar signs or as a block between double dollar signs. The renderer spots it and converts it to proper mathematical typesetting. GitHub, GitLab, Obsidian, Jupyter notebooks and most academic tooling handle this. A plain CommonMark renderer will show you the dollar signs and the raw backslash commands.
Diagrams are usually Mermaid, a text syntax for flowcharts, sequence diagrams and Gantt charts written inside a fenced code block tagged mermaid. Where it's supported the block renders as a picture. Where it isn't, it renders as a code block showing the diagram's source, which at least degrades to something readable rather than to nonsense.
That difference in failure mode is worth planning around:
- Check the destination before you rely on either. A README that renders beautifully on GitHub can arrive as symbol soup in a documentation site using a different parser.
- Diagrams degrade better than maths. An unrendered Mermaid block still looks like a deliberate code block. An unrendered equation looks like a mistake.
- For anything that must render everywhere, export an image. A PNG or SVG of the diagram works in every renderer ever written. You lose the ability to diff the source in version control, which is the main reason to use Mermaid in the first place, so it's a real trade rather than an obvious win.
- Always write alt text if you do export an image. A diagram carrying real information is not decoration, and the accessibility section below applies to it.
The general rule holds. If the content has to survive being moved between tools, keep to the common core. If it lives in one place you control, use whatever that place renders.
Is it safe to render Markdown other people wrote?
Not on its own, no. And this catches out more developers than any syntax quirk, because the danger is in what Markdown deliberately allows rather than in anything going wrong.
Markdown passes raw HTML straight through. The CommonMark spec is explicit about it, defining an HTML block as a group of lines "treated as raw HTML (and will not be escaped in HTML output)". That is the behaviour, working as designed. A parser that stripped your HTML would not be following the spec.
Which is fine when you wrote the document. It is a problem the moment the Markdown came from someone else, because a script tag in their input becomes a script tag in your page.
Here is the detail that makes the point better than any warning. Search the whole CommonMark spec for the phrase "for security reasons" and you get exactly one hit, and it is about replacing the null character U+0000 with U+FFFD. Not about script tags. Not about links. The spec simply is not trying to solve this, and it says so by omission: sanitisation is treated as an implementation concern, not a specification one.
So the safety of rendering user Markdown depends entirely on the parser you picked and how you configured it, and the defaults are usually permissive to stay spec-compliant. If you are building anything that renders Markdown from users, comment forms, wikis, support tickets, issue trackers, do one of these:
- Turn on your parser's safe mode. Most mature libraries have one. It escapes raw HTML, or strips it, or renders it as a comment, and usually blocks link URLs that do not match an allowlist of schemes.
- Or sanitise the HTML output afterwards with a dedicated sanitiser, rather than trying to filter the Markdown source with regular expressions. Filtering the input is a losing game.
Do not assume a well-known parser is safe by default. Being spec-compliant and being safe with untrusted input are different goals, and the popular libraries mostly optimise for the first. Check the option rather than trusting the reputation.
Doesn't GitHub Flavored Markdown filter dangerous tags?
It filters nine of them, and knowing exactly which nine matters, because it is far less protection than it sounds like.
The GitHub Flavored Markdown Spec, version 0.29-gfm dated 6 April 2019, defines five extensions on top of CommonMark. Four are the ones everyone knows: tables, task list items, strikethrough and autolinks. The fifth is Disallowed Raw HTML, and it does one narrow thing. For title, textarea, style, xmp, iframe, noembed, noframes, script and plaintext, it replaces the leading < with < so the tag prints as text instead of running.
Now read the spec's reason for it, because it is not the reason you would guess. The problem it names is that a document containing those tags will not be parsed properly by an HTML5-compliant parser, which then swallows the Markdown content that comes after them. So the filter exists to stop the rest of your document vanishing. Blocking a script tag is a side effect of fixing a parsing failure.
Which is exactly why you should not read it as a sanitiser. It is a denylist of nine tag names. An onerror attribute on an image, a javascript: URL inside a link, an onclick on anything at all: none of those are on the list, and none of them get filtered. If your input is untrusted, nine tag names is not the control you are looking for.
So the conclusion above holds, just more precisely. GFM specifies more here than CommonMark does, and still nothing close to enough. Turn on your parser's safe mode or sanitise the output properly. Treat the nine tags as a parsing fix you happen to get for free, not as a security feature you can lean on.
None of this applies to writing your own README or notes. It matters the moment the text is not yours.
Does your Markdown produce accessible HTML?
Only if you write it carefully, and this is the part almost every Markdown guide skips. Markdown compiles to HTML, so whatever you type becomes the semantic structure a screen reader navigates. Four habits do most of the work.
Are you using headings for structure or just for size?
This is the big one. In Markdown it's tempting to pick ### because ## looked too big, which quietly breaks the document outline for anyone not reading with their eyes.
The W3C's Web Accessibility Initiative is direct about it. Their page structure tutorial says to "nest headings by their rank (or level)" and that "skipping heading ranks can be confusing and should be avoided where possible," with the specific instruction to make sure an h2 is not followed directly by an h4. In Markdown terms: don't jump from ## to ####.
Why it matters more than it looks. As WAI puts it, "headings communicate the organization of the content on the page," and browsers, plug-ins and assistive technologies use them for in-page navigation. Screen reader users routinely jump heading to heading to survey a document. A broken hierarchy turns that into guesswork.
This sits under WCAG 2.2 Success Criterion 1.3.1, Info and Relationships, at Level A, the minimum conformance bar. Its normative text requires that "information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text." A heading that's only a heading because it looks big fails that test.
Practical fix: pick the level by where the section sits in the outline, then style it separately if it's too large. And use one # per document, since that's your page title.
What else breaks accessibility in Markdown?
Three things, all cheap to get right.
- Empty alt text on images. The syntax is
, and the bit before the brackets is the alt text. Writingships an image with nothing to announce. Describe what the image conveys, and if it's purely decorative, leave the alt genuinely empty on purpose rather than by accident. - Link text that says nothing.
[click here](url)and[read more](url)are useless when a screen reader lists every link on the page out of context. Put the destination in the text:[the CommonMark spec](url). - Tables without header rows. Markdown tables need that
---separator line to produce real table headers in the HTML. Skip it and you get a grid of cells with no relationships. WCAG's guidance under the same 1.3.1 criterion notes that where items are organized into a table, "the relationship of each cell to its row and/or column header" is necessary for understanding.
None of this costs you anything at writing time. It just requires deciding once that the structure is the point and the appearance is a side effect. Which, as it happens, is the whole idea behind Markdown anyway.
What trips people up most often?
Five things, in roughly the order you will hit them.
Missing blank lines. Markdown uses blank lines to separate blocks. Two paragraphs on consecutive lines usually become one paragraph. This is the single most common mistake and the easiest to fix.
Tables that do not exist. Covered above. Tables are a GitHub Flavored extension, not base Markdown.
Underscores inside words. A variable name like my_var_name can trigger italics in some parsers, because underscores are an emphasis marker. Wrap code in backticks and the problem disappears.
Inconsistent list indentation. Original Markdown never pinned this down, which is why two spaces works in some parsers and four in others. CommonMark does pin it down, and the rule is worth knowing: section 5.2 sets the required indent at the width of the parent marker plus the spaces after it, so a sublist lines up with where the parent's text starts. That is 2 for - , 3 for 1. and 4 for 10. . It catches people out on numbered lists, where two spaces nests a bullet fine but leaves an ordered item flat. Four spaces still works nearly everywhere if you would rather not count.
Trailing whitespace as a line break. Two spaces at the end of a line means a line break in most flavours. It is invisible, editors strip it, and it is a genuinely bad piece of design. Use a blank line instead where you can.
Where should you break lines in the source?
Wherever suits you, because it makes no difference to what readers see. This is the flip side of the trailing whitespace problem above, and hardly anyone gets told about it.
The CommonMark specification is explicit in section 6.8. It defines a soft line break as a line ending that is not a hard line break, and says it "is treated as a space". So a newline in the middle of a paragraph does not survive into the output as a break. It becomes a space, exactly as though you had carried on typing.
Which means the shape of your source file is entirely your call. Write a paragraph as one very long line, wrap it at eighty characters, or start a new line after every sentence, and all three render identically.
So choose the shape that helps the diff. One sentence per line is the convention worth knowing. Change a single sentence in a long paragraph and version control reports one changed line with everything around it untouched. Write that same paragraph as one long line and a single word change reports the whole paragraph as modified, which buries the actual edit and makes review harder than it needs to be.
It costs nothing, readers never see it, and if you write anything other people review it is probably the highest-value habit on this page. Our text diff tool shows you the difference on your own writing in about a minute.
Why did your list suddenly get extra spacing?
Because you put a blank line in it, and that quietly changed what the list compiles to.
Markdown lists come in two kinds, and almost nobody is told this. The CommonMark specification names them in section 5.3: a list is loose if any of its items are separated by blank lines, or if any item directly contains two block-level elements with a blank line between them. Otherwise it is tight.
The spec is blunt about what changes. "The difference in HTML output is that paragraphs in a loose list are wrapped in <p> tags, while paragraphs in a tight list are not." That is the whole mechanism. A tight list gives you <li>Item</li>. A loose one gives you <li><p>Item</p></li>, and those paragraph tags carry your stylesheet's paragraph margins with them.
So the extra gap you are seeing isn't the list being temperamental. It's CSS doing exactly what you told it to do to a paragraph, in a place you didn't realise had become one.
What this means in practice:
- One blank line changes the whole list, not one item. Loose and tight are properties of the list, so a single blank line between two items reformats every item in it. That is why the spacing shift looks disproportionate to the edit.
- It is not a bug to route around. If your items are single lines, keep the blank lines out. If any item needs two paragraphs, the list has to be loose, and fighting it with CSS hacks is solving the wrong problem.
- Watch your formatter. Tools that reflow Markdown can add or remove the blank lines between items, which silently flips a list from tight to loose and changes the rendered spacing without touching a word of your text.
It is a small rule with an outsized effect on how a page looks, and it explains a category of "my Markdown looks wrong" that people usually blame on the renderer.
Does Markdown work properly in Chinese, Japanese and Korean?
Mostly, but bold and italic break in one specific and genuinely maddening way. And when they do, it isn't your editor being buggy. It's the specification behaving exactly as written.
Here's the shape of it. Put punctuation inside the emphasis and it silently stops working:
**テスト。**テスト does not render as bold
**テスト**。テスト renders fine
Same characters, same markers. The only thing that moved was the full stop, and one version quietly ships as literal asterisks.
The cause sits in how CommonMark decides whether a run of asterisks is allowed to close emphasis. The spec says a right-flanking delimiter run is one that is "(1) not preceded by Unicode whitespace, and either (2a) not preceded by a Unicode punctuation character, or (2b) preceded by a Unicode punctuation character and followed by Unicode whitespace or a Unicode punctuation character."
Now walk the failing line through that. The closing asterisks come straight after a full-width full stop, which is a Unicode punctuation character, so clause 2a is out. That leaves 2b, which would rescue it if the asterisks were followed by whitespace or more punctuation. They're followed by another character, because Japanese doesn't put spaces between words. So 2b fails too, the run never qualifies as right-flanking, and there's nothing to close the emphasis with.
Which explains why English almost never hits this. Write "**what I wanted to do.** So I am going to do it" and the closing asterisks are also sitting after a full stop, but a space follows them. Clause 2b catches it and the bold renders. The space you never think about is doing the work.
This is a known open issue on the CommonMark specification's own tracker rather than a quirk of any one tool, and it's been discussed since 2020 without a resolution landing in the spec. So treat it as current behaviour to write around, not a bug awaiting a patch.
What to do about it:
- Move the punctuation outside the markers. The single most reliable fix, it costs nothing, and it survives every renderer. Emphasise the words, then punctuate.
- Don't trust your editor as proof. Some tools ship CJK-friendly emphasis patches or plugins, which is helpful locally and misleading globally. Your file will render somewhere else eventually, and that somewhere probably follows the spec.
- Reach for HTML when it has to be exact. A literal <strong> tag has no flanking rules to satisfy, which is the same reasoning as the HTML section above.
- Test in the actual target. Paste a sample into the platform that will publish it before writing three thousand words that quietly lose their formatting.
- Watch mixed scripts especially. Text that switches between CJK and Latin, or that uses full-width brackets and quotation marks, gives the flanking rules more chances to trip.
And this stacks on top of the flavour problem covered earlier. A document can be valid CommonMark, render correctly in one place, and lose its emphasis in another, purely because of which characters happen to sit next to your asterisks.
Can you get a tool to fix your Markdown for you?
Yes, and it is the honest answer to the whole list above. Every gotcha in the previous section is a rule a machine can check faster and more reliably than you can remember it. Two kinds of tool do this, they do different jobs, and most people who write Markdown daily run both without thinking about it.
A linter tells you what is wrong. The standard one is markdownlint, maintained by David Anson, which ships roughly 60 rules. What makes it worth mentioning here is how directly those rules map onto the mistakes listed above. Trailing whitespace as an invisible line break is MD009. Inconsistent sublist indentation is MD007. Mixing hyphens and asterisks for bullets in the same document is MD004. Skipping from an H2 to an H4, the accessibility problem covered earlier, is MD001. The rules are numbered and individually switchable, so you can turn off the ones you disagree with and keep the rest.
A formatter just rewrites the file. Prettier is the usual choice, and the distinction matters: a linter reports, a formatter fixes silently on save. Prettier normalises your emphasis markers, list indentation and spacing to one house style, so the question of whether you indented two spaces or four stops being a question. Its Markdown support is built on remark and micromark, and Prettier 3.9 moved the parser to micromark v4 specifically to improve CommonMark and GFM compliance.
Notice what that means. Prettier is choosing to be judged against CommonMark, the same spec with its 652 conformance examples from earlier in this guide. A formatter is only as trustworthy as the spec it targets, which is the practical payoff of Markdown having been pinned down at all. Before CommonMark there was nothing precise enough for a formatter to be correct about.
Worth being clear about the limits. Neither tool can tell you your writing is unclear, and neither will catch a table you wrote in a flavour that does not support tables, because the syntax is valid, it just renders as literal text. Linting checks consistency, not meaning. But if you write Markdown in a repo where more than one person touches the files, a linter in CI plus a formatter on save removes an entire category of pointless review comments. Nobody should be spending a code review arguing about bullet characters.
For one-off writing, none of this is worth setting up. Paste into our free Markdown editor and watch the preview, which catches the blank-line and indentation problems just as effectively when the document is short.
How do you get Markdown out into Word or PDF?
With pandoc, in one command, and it handles far more than the two formats in that heading.
This is the situation nobody warns you about. You wrote the document in Markdown because it was pleasant to write. Then someone asks for a .docx, or a PDF to print, or the content pasted into a CMS that only speaks HTML. Markdown's readability stops being the point the moment the destination is somebody else's tool.
Pandoc describes itself as a universal document converter and a swiss-army knife for moving between markup formats. It's free software under the GPL. It reads Markdown including CommonMark and GitHub Flavored, with extensions for footnotes, tables, definition lists, superscript and subscript, and strikeout. On the way out it produces Word docx, PDF, HTML5, LaTeX, EPUB, RTF and PowerPoint, among a long list of others.
Notice who wrote it. Pandoc is by John MacFarlane, the same person who wrote the CommonMark specification quoted earlier in this guide. That isn't a coincidence worth glossing over. You cannot convert a format reliably until somebody has pinned down what it means, and the person who did the pinning is the person who built the converter.
What actually goes wrong
- PDF needs a separate engine. Pandoc doesn't produce PDF by itself, it routes through LaTeX or another engine, so PDF output fails until you install one. This is the most common first-time stumble and it looks like pandoc is broken when it isn't.
- Word out is reliable, Word in is messy. Markdown to docx works well. Somebody's docx back to Markdown is a different job, because Word carries styling, tracked changes and layout that Markdown has no concept of. Expect to clean up rather than expecting a clean round trip.
- Your output will look like pandoc's defaults, not your organisation's. The fix is a reference document: hand pandoc an existing .docx and it takes its styles from that, so headings and body text match your house template.
- Front matter finally earns its keep. The YAML block from earlier in this guide is where pandoc reads the title and author for the generated document. So that block isn't only a static site generator thing.
Does this change which flavour you should write?
A little, and it's the same trap this whole guide keeps circling.
Pandoc is itself one of the eight variants registered in RFC 7764. Pandoc's Markdown has its own extensions that plain CommonMark does not, so a document written to use them converts beautifully through pandoc and renders as literal text somewhere else. Same rule as everywhere: if the file has to work in more than one place, stay near the common core and treat the extras as a local convenience.
And know when not to bother. If you only need to read the thing, a preview pane is faster. If it's a short one-off, copying from a rendered preview into Word usually just works. Pandoc earns its setup cost when the conversion is repeated, scripted, or has to look consistent every time. For a quick look at rendered output, our free Markdown editor does the job with nothing to install.
Which places actually use Markdown?
More places than you would guess, which is the argument for learning it once.
Every README on GitHub and GitLab. Issue and pull request descriptions. Slack and Discord messages, in a reduced form. Note-taking apps like Obsidian and Notion. Static site generators. Most modern documentation platforms. Plenty of content management systems. And increasingly, prompts and outputs when working with AI tools, which tend to read and write Markdown natively.
The reason it keeps winning is that the source file is useful even with nothing installed. An HTML document you cannot render is a mess of tags. A Markdown document you cannot render is just a nicely organised text file, which is exactly what Gruber was aiming for in 2004.
If you are assembling a wider toolkit, our guide to online developer tools and the free tools for developers roundup cover what else is worth bookmarking.
Why does AI chat output break when you paste it somewhere else?
Because the model wrote Markdown and you pasted it somewhere that does not render Markdown, or renders a different flavour of it. This is the same flavour problem from the top of this page, just arriving by a route nobody had in 2015.
Every mainstream chat assistant emits Markdown by default. Headings, bold, bullet lists, fenced code blocks, and usually GitHub Flavored tables. Inside the chat window it renders, so you never see the raw text. Copy it out and the raw text is all you get.
Where it survives the trip: anything that already speaks CommonMark or GFM. GitHub issues, most static site generators, most documentation tools, and our Markdown editor if you want to see the rendered version before you commit to anything.
Where it does not:
- Anywhere expecting plain text. An email body, a form field, a CMS box that is not Markdown aware. You get literal asterisks and hash marks, which is worse than if you had never formatted it.
- Slack, which is the one that catches people. It looks like it should work, and it half does, which is the worst outcome.
- Word and Google Docs. A paste is plain text unless you convert first. Pandoc, mentioned earlier, is the reliable way to do that.
The Slack case is worth spelling out because it is so common. Slack's own formatting documentation states that mrkdwn is "inspired by markdown, but uses different rules." The differences are exactly where model output lands:
- Bold is
*bold*in Slack, not**bold**. So the model's double asterisks show up as visible asterisks. - Strikethrough is
~strike~, not~~strike~~. - Links are
<url|text>, not[text](url). Standard Markdown link syntax stays raw on screen.
Three ways out, in ascending order of effort. Ask the model for the format you actually need, because "give me that as plain text" or "format that for Slack" works and almost nobody tries it. Paste into a renderer and copy the rendered output, which handles Word and email. Or run it through Pandoc when you are converting something long enough to be worth the setup.
The underlying lesson is the one this whole page keeps returning to. Markdown is not a thing your text is, it is a thing the destination either understands or does not. Knowing which one you are pasting into is most of the battle.
What else do people ask about Markdown?
Is Markdown a single standard?
No. RFC 7763, which registered the text/markdown media type with the IETF in March 2016, describes Markdown as a family of related plain-text formatting syntaxes rather than one language. It even set up an IANA registry so a document can declare which variant it was written in. Treat Markdown as a family and check which one your platform speaks.
Why does my Markdown look different on different sites?
Because implementations genuinely disagree. The CommonMark specification says John Gruber's original description does not specify the syntax unambiguously, lists 14 separate examples of ambiguity, and notes that implementations have diverged considerably, so the same document can render one way on a GitHub wiki and differently through pandoc.
What is the difference between CommonMark and GitHub Flavored Markdown?
CommonMark is the strict base specification that pins down the ambiguous cases. GitHub Flavored Markdown is CommonMark plus extras: tables, strikethrough, task lists and autolinked URLs. If you write a table in plain CommonMark it will not render, which is the single most common surprise for people moving between platforms.
When should you use HTML instead of Markdown?
When you need control Markdown does not offer: specific attributes, classes, nested layout, colspan in a table, or precise image sizing. Markdown covers the common ninety percent of formatting and deliberately stops there. Most Markdown processors let you drop raw HTML inline for the rest, though some sanitise it away.
Do you need to learn Markdown to use it?
Barely. Six pieces of syntax cover almost everything most people write: hash for headings, asterisks for emphasis, hyphen for bullets, square brackets and parentheses for links, backticks for code, and a blank line between paragraphs. That is roughly twenty minutes of learning for a format you will use for years.
Sources: Internet Engineering Task Force, RFC 7763, The text/markdown Media Type, Sean Leonard, March 2016, on the registered media type, the variant parameter and Markdown as a family of related syntaxes. Internet Engineering Task Force, RFC 7764, Guidance on Markdown: Design Philosophies, Stability Strategies, and Select Registrations, Sean Leonard, March 2016, Informational, on the eight variants registered in the IANA Markdown Variants registry. CommonMark Specification version 0.31.2, John MacFarlane, 28 January 2024, on the 14 documented ambiguities in the original syntax, on implementations having diverged considerably, and on the 652 worked examples the spec states are intended to double as conformance tests. RFC 7764 also covers the absence of any metadata mechanism in the original syntax, the front matter and title block conventions that grew up to fill it, and mathematical formulae as one of the drivers behind new Markdown variants. Pandoc project documentation, pandoc.org, on pandoc as a universal document converter, the Markdown variants it reads including CommonMark and GitHub Flavored, its output formats including docx, PDF, HTML5, LaTeX, EPUB, RTF and PowerPoint, and its GPL licensing. Pandoc is written by John MacFarlane, who also authored the CommonMark specification cited above. Mozilla, Markdown in MDN, MDN Web Docs writing guidelines, developer.mozilla.org, on GitHub Flavored Markdown as the MDN baseline, the definition list and example code block extensions, and the rule that HTML is used when GFM cannot express a table or when the GFM version would run wider than 150 characters. GitHub Flavored Markdown Spec, version 0.29-gfm, 6 April 2019, github.github.com/gfm, on GFM being a strict superset of CommonMark, its five extensions of tables, task list items, strikethrough, autolinks and Disallowed Raw HTML, the nine filtered tag names title, textarea, style, xmp, iframe, noembed, noframes, script and plaintext, the mechanism of replacing the leading angle bracket with an entity, and the stated rationale that these tags stop an HTML5-compliant parser handling the document correctly and cause it to swallow following content. Specifications and software are living things, so check the current version before relying on a detail. GitHub Docs, Basic writing and formatting syntax, on alerts as a Markdown extension based on the blockquote syntax, the five types NOTE, TIP, IMPORTANT, WARNING and CAUTION, the rule that alerts cannot be nested within other elements, and the guidance to limit them to one or two per article and avoid placing them consecutively. Alerts do not appear in the GFM spec version 0.29-gfm. CommonMark version 0.31.2 was confirmed as the current specification release at the time of writing.