CommonMark says one thing. GitHub says another. Slack ignores the conversation entirely. Here's what actually diverges — and where it'll ruin your carefully formatted document.
Markdown is supposed to be simple. Write some asterisks, get bold text. Write some hyphens, get a list. The problem is that "simple" became "popular," and popular things attract implementations, and implementations drift. There's CommonMark (the closest thing to a canonical spec), GitHub Flavored Markdown (a superset with tables and task lists), Pandoc (its own superset with grid tables and definition lists), and then a zoo of platform dialects — Slack, Notion, Reddit, Bear, Obsidian — each picking which bits to honour and inventing the rest.
The result: write something in your local editor, paste it into GitHub, discover the table is mangled, fix it for GitHub, paste it into Notion, find that Notion has opinions of its own. These seven differences account for most of those surprises.
1. Line breaks: three kinds, and they don't agree
A blank line creates a paragraph break everywhere — that part's consistent. Everything else is negotiable.
CommonMark defines two ways to force a line break within a paragraph: two trailing spaces before the newline, or a backslash before the newline. Both render as <br>. A single newline with no trailing spaces is a soft break — it collapses to a space in the output, invisible in most rendered HTML.
GFM adds a fourth option via the "hard_wrap" extension (GitHub's default): a single newline in source becomes a hard line break. This is why READMEs on GitHub render mid-paragraph line breaks where strict CommonMark parsers would ignore them. Copy that content to a tool using strict CommonMark and your poem or structured list becomes one flowing paragraph.
Slack follows neither rule. It has its own line-break model that predates any Markdown standard and treats every newline as meaningful. Notion's import behaviour depends on whether you're pasting or using the API.
"A hard line break is a backslash before the end of the line, or two or more spaces before the end of the line."
— CommonMark Spec §6.7 (CC BY-SA 4.0)
Practical rule: don't rely on trailing-space hard breaks for anything you'll move between platforms. Use a blank line to separate paragraphs, or write explicit <br> if you need a break that survives everywhere.
2. Tables: GFM only, and the header row is not optional
Tables are among the most-used Markdown features despite not appearing in the CommonMark spec at all. GFM defines them with pipe delimiters and a mandatory separator row of dashes under the header. Column alignment is set with colons: :--- for left, ---: for right, :---: for centre.
| Name | Score |
|:--------|------:|
| Alice | 98 |
| Bob | 83 |
The trap: the separator row isn't optional. Drop it and GFM won't parse the table at all — you get literal pipe characters. Pandoc uses a different table syntax (grid tables, multiline tables) that GFM doesn't support. Pure CommonMark renderers — including older versions of some static site generators — render GFM tables as text. If you paste a table from GitHub into a tool running strict CommonMark, every pipe and dash shows up raw.
The Markdown table editor lets you build and align tables visually without counting pipes by hand, which helps when columns need to line up for readability.
3. Strikethrough: tilde syntax is GFM, not spec
~~strikethrough~~ is a GFM extension. CommonMark has no strikethrough syntax. Use it in a strict CommonMark renderer and you get literal tildes flanking your text. Some platforms (Jira's wiki markup, certain Slack contexts) use single tildes ~like~ instead — so even the GFM convention isn't universal.
If you need strikethrough that survives a portability trip, use <del>text</del> where inline HTML is supported (GitHub, most static site generators). On platforms that strip HTML, you're out of luck regardless.
4. Fenced code blocks: the language hint and the nesting trap
Triple-backtick fenced code blocks are widely supported and the syntax is broadly consistent. The friction lives at the edges.
First, the language hint must immediately follow the opening fence with no space in most parsers: ```python not ``` python. Some parsers tolerate the space; others silently drop the syntax highlight class. Test your renderer if syntax highlighting matters.
Second, you can't use triple backticks to fence a block that itself contains triple backticks — for example, when writing documentation about Markdown. The workaround is a longer fence: four backticks, or switch to tildes (~~~) for the outer fence. CommonMark explicitly supports this.
Third, watch for indented code blocks competing with fenced ones. If a fenced block is inside a list item and the indent level is ambiguous, some parsers interpret the content as an indented code block before they see the fence markers, producing garbage.
5. Inline HTML: allowed, sanitized, or stripped
CommonMark explicitly allows inline HTML. You can write <kbd>Enter</kbd>, <mark>highlighted</mark>, or a <details>/<summary> collapsible block and they render correctly in most static-site contexts.
GFM sanitizes a subset of dangerous tags — script, iframe, object, embed — for XSS prevention when rendering untrusted user content. The safe tags work. Slack strips nearly all HTML. Notion preserves a narrow list of inline elements and discards the rest.
The consequence: Markdown with embedded HTML for rich formatting works beautifully on GitHub and most SSGs, shows as literal angle-bracket noise on Slack, and partially renders on Notion with no warning about what was dropped. If you're writing Markdown that needs to live in multiple contexts, treat inline HTML as a GitHub/local-only feature.
6. Autolinks: angle brackets required in strict CommonMark
In GFM, a bare URL in running text — https://example.com — becomes a hyperlink automatically. This is the GFM autolink extension, on by default in GitHub's renderer. In strict CommonMark, bare URLs are literal text. To get a link you need either [text](url) syntax or angle brackets: <https://example.com>.
The pain: GFM-heavy docs pasted into a strict CommonMark context turn every bare URL into a long unlinked string. Go the other direction and angle-bracketed links sometimes render as visible brackets in platforms that expect the bare-URL form.
Use explicit [text](url) for any link you care about. Reserve bare URLs for throwaway contexts where you're certain the platform supports autolinks.
7. Nested list indentation: the blank-line trap
This one has caused more "but it was working five minutes ago" moments than any other Markdown quirk.
The original Markdown.pl (Gruber, 2004) required 4-space indentation for nested list content. CommonMark changed this to a context-dependent count: a sub-list needs to be indented past the content start of the parent item, which is typically 2 or 3 spaces depending on the marker used. GFM follows CommonMark. Many older converters still expect 4 spaces.
The nastier trap: add a blank line between list items to get "loose" formatting (more paragraph-like spacing), and a sub-list indented by only 2 spaces may stop being recognised as a sub-list — the blank line changes the parser state. This is specced behaviour, but it surprises almost everyone the first time. The fix is to use consistent 4-space indentation for nested content, which works in both the old-school and modern conventions.
The practical takeaway
Basic Markdown — headers, bold, italic, links, code spans, blockquotes — works everywhere. The divergence lives entirely in extensions. When you're writing for one platform, use its flavor and don't worry about it. When you're writing content that'll move between platforms or be published through a build pipeline, stick to CommonMark core, use explicit HTML only where it's welcome, and test tables and line breaks early rather than after you've written 2,000 words.
The Markdown to HTML converter will show you exactly how CommonMark renders your source — useful when you can't tell whether a rendering quirk is in your Markdown or your editor's preview. For content headed to PDF, Markdown to PDF applies a clean stylesheet that sidesteps platform rendering differences entirely.
← All articles