Markdown flavors: CommonMark, GFM, and the variants in between
“Markdown” is plural — there are several specs and many extensions. This article surveys the main flavors and the diff that bites you when porting between them.
Why flavors emerged
The original Markdown (John Gruber, 2004) was loosely specified, so implementations diverged:
- No defined table syntax.
- Nested-list rules varied.
- Hard-break (
<br>) handling was implementation-dependent.
CommonMark unified the core; GFM and others added features.
CommonMark — the standard
CommonMark is a strict specification. Most modern Markdown tooling targets it:
- Nested lists, blockquotes, code blocks have well-defined behavior.
- No tables, task lists, or strikethrough — those are extensions.
- Implementations: pandoc, commonmark.js, cmark…
CommonMark alone lacks several “modern Markdown” niceties.
GitHub Flavored Markdown (GFM)
The GitHub dialect — CommonMark + extensions:
Extensions
| Col 1 | Col 2 |
| ----- | ----- |
| a | b |
- [x] done
- [ ] todo
~~strikethrough~~
https://example.com (autolink) Notable additions
- Tables — pipes and dashes.
- Task lists —
[ ][x]. - Strikethrough —
~~text~~. - Autolinks — bare
http://...becomes a link. - Emoji shortcodes —
:smile:→ 😄.
GitHub, GitLab, Bitbucket, and most doc platforms target GFM.
MDX
JSX inside Markdown — embed React components directly:
import Chart from './Chart';
# Data viz
<Chart data={[1, 2, 3]} /> - Used by Docusaurus, Next.js, Astro.
- Good for interactive docs.
mdsvex (Svelte’s MDX)
Embeds Svelte components in Markdown:
<script>
import Counter from './Counter.svelte';
</script>
# Heading
<Counter /> Common in SvelteKit doc sites.
Pandoc Markdown
Pandoc’s own flavor:
- LaTeX math.
- Bibliography / citations.
- Table captions.
- Definition lists.
- Custom headers / footers.
Powerful for academic and book publishing — but it’s not a strict superset of GFM.
Obsidian / Bear
Note-app extensions:
- Wiki links —
[[NoteName]] - Tags —
#tag - Highlights —
==important== - Image embeds —
![[image.png]]
None of these are GFM or CommonMark.
Common compat traps
Hard line breaks
CommonMark — two trailing spaces:
Hello␣␣
World GFM has a “soft break renders as <br>” mode in some surfaces (GitHub Issues / PRs) but not in regular READMEs.
Lists and adjacent paragraphs
- list item
This is a paragraph CommonMark — paragraph is outside the list. Some tools — treats it as a list-item continuation.
Ordered list start number
3. third
4. fourth CommonMark — starts at 3. Old implementations — silently reset to 1.
HTML inside code blocks
```
<div>
``` Most flavors render the <div> literally (no HTML interpretation). Older implementations sometimes confuse it.
Table limits
GFM tables are constrained:
- No multi-line cells — fake it with
<br>or avoid. - No row spans / col spans.
- Easy to misalign — columns of different widths look bad in source.
For complex tables, drop to HTML:
<table>
<tr>
<td>multi<br />line</td>
</tr>
</table> Math
CommonMark has no math. Extensions:
- GFM — KaTeX (
$...$and$$...$$on GitHub). - Pandoc — LaTeX math.
- MDX — KaTeX / MathJax components.
Inline: $E = mc^2$
Block:
$$
int_a^b f(x) dx
$$ Heading anchors
Headings get auto-generated anchor IDs:
## My section
[link](#my-section) Slug rules vary by tool:
- GFM — lowercase, spaces → hyphens, strip punctuation.
- Some tools — transliterate non-ASCII or drop it.
Cross-site link breakage usually traces back to slug differences.
Escaping
Backslash to keep * _ literal:
*not bold* GFM extends escapes to ~ < > etc.
Summary
- CommonMark is the standard, GFM is the de-facto.
- Tool-specific extensions (MDX, Obsidian, Zenn) reduce portability.
- Tables, math, and hard breaks are the most divergent.
- For maximum portability, stick to GFM.
To preview Markdown rendering and check formatting, the markdown preview tool on this site shows the GFM rendering.