Type **done** in a GitHub comment, and it appears as done. Add # to a README line, and it becomes a heading. Paste the same text elsewhere, and a table may collapse into pipes and dashes. These moments share one idea; understanding it makes them feel predictable.

Markdown is plain text that programs convert into HTML (HyperText Markup Language), which browsers display. This article explains why Markdown exists, how renderers process it, why its meaning varies by context, and when it’s unsuitable.

A Syntax and a Tool

Markdown is both a plain-text formatting syntax and a Perl software tool that converts it to HTML. John Gruber developed it with Aaron Swartz in 2004, according to the CommonMark project’s history. The original script’s final release, Markdown 1.0.1, dates to 17 December 2004.

Today the word mostly means the syntax, and dozens of other programs read the same conventions.

Here is a short Markdown document:

## Release notes

The import job is **faster** and skips *empty* rows.

* Fixed the date parser.
* Added a `--dry-run` flag.

Read the [full changelog][changelog].

[changelog]: https://example.com/changelog

Even if you’ve never seen Markdown, you can read it, and Gruber designed it so you could.

Why Markdown Exists

Before Markdown, web writing meant hand-coding HTML or using a rich text editor. HTML hides words in tags: bolding one word yields The import job is <strong>faster</strong>., while a list requires opening, item, and closing tags. Editors conceal tags but produce markup that’s hard to read, compare, or fix.

Gruber drew on familiar plain-text formatting. His syntax documentation identifies plain-text email as the main inspiration, where people used *emphasis* and dashes for lists before renderers supported them. Earlier text-to-HTML filters, including Setext, atx, Textile, and reStructuredText, also influenced it.

His strict goal: Markdown files should work as plain text, ready to publish without looking marked up. This explains most of Markdown’s choices.

A # heading and blank-line paragraph break should remain clear in the source, even without rendering.

How Markdown Works

A Markdown file is document source code: a parser builds its structure, and a renderer converts it to HTML. Since most tools combine both, the whole tool is often called a renderer. CommonMark implementations use two broad parsing passes, following the strategy the CommonMark spec describes:

  • Blocks first. It divides text into blocks—headings, paragraphs, lists, quotes, and code—using blank lines, leading # characters, list markers, and indentation to mark boundaries.
  • Inlines second. Within each block, it detects inline structures—emphasis, links, code, and images—marked by *, backticks, and square brackets.

The two passes build a nested document tree of headings, paragraphs, and inline pieces, which the renderer writes as HTML. The pipeline looks like this:

flowchart TB A["Markdown file (plain text)"] --> B["Block pass: headings, paragraphs, lists, code"] B --> C["Inline pass: emphasis, links, code spans"] C --> D["Document tree"] D --> E["HTML"] E --> F["Browser shows the page"]

Render the release notes above to get roughly this:

<h2>Release notes</h2>
<p>The import job is <strong>faster</strong> and skips <em>empty</em> rows.</p>
<ul>
<li>Fixed the date parser.</li>
<li>Added a <code>--dry-run</code> flag.</li>
</ul>
<p>Read the <a href="https://example.com/changelog">full changelog</a>.</p>

The source’s final line, [changelog]: https://..., is omitted because the renderer treats it as a definition and uses it wherever [changelog] appears.

A recipe is a useful analogy: Markdown is the readable recipe card, the renderer is the cook, and HTML is the plated dish. Give two cooks the same card, and their dishes will look alike but differ in details.

Why Markdown Has Flavors

Gruber documented the syntax through prose and examples, not a formal grammar, leaving gaps—such as whether lists could follow paragraphs without a blank line or how many spaces nested them. Renderer authors answered differently.

The CommonMark project says Gruber’s description does not specify the syntax unambiguously. By 2014, dozens of implementations had diverged: a document could render differently on GitHub wiki and Pandoc.

Since 2014, CommonMark has provided a clear specification and self-checking test suite. Its latest version is 0.31.2, dated 28 January 2024.

Flavors add features to the shared core that the original lacked:

  • GitHub Flavored Markdown (GFM). GitHub’s spec is a strict superset of CommonMark, adding tables, task lists (- [ ]), strikethrough, bare-URL autolinks, and filtering risky raw HTML tags like <script>.
  • Site generator flavors. Hugo, this blog’s static site generator, uses Goldmark, which conforms to the CommonMark specification and supports GFM. Hugo also enables footnotes, definition lists, and typographic quotes by default.
  • Tool-specific flavors. Note, chat, and documentation apps each support different subsets, often without specifying which.

So “this is Markdown” is closer to “this is English” than “this is Python 3.12”: the core is shared, and the dialect depends on context.

How Markdown Relates to HTML, Git, and Other Formats

Markdown makes more sense next to the formats around it.

  • HTML. Markdown fronts HTML. Gruber says, HTML is a publishing format; Markdown is a writing format. If Markdown lacks a feature, you can write HTML directly in the file.
  • Plain text and version control. Because Markdown is plain text, Git can diff it line by line. This makes it ideal for READMEs, changelogs, architecture decision records, documentation sites, and writing good technical docs, which often starts in a .md file.
  • Other lightweight markup. reStructuredText and AsciiDoc solve the same problem, offering richer built-in structure, such as admonitions and cross-references, at the cost of more syntax to learn.
  • The text/markdown media type. RFC 7763, an IETF Request for Comments registered text/markdown in March 2016 and assigned the extensions .md and .markdown. It describes Markdown as “a family of plain-text formatting syntaxes,” treating its flavors as part of the format.
  • Diagrams as text. Tools like Mermaid use the same idea: describe a diagram in a fenced plain-text code block, then let a renderer draw it.

Trade-offs and Limitations

Markdown prioritizes writing over layout, with predictable trade-offs.

  • Portability is partial. CommonMark-only files travel well; tables, footnotes, and task lists rely on specific flavors, so some tools display raw pipes and brackets.
  • Structure is shallow. Markdown supports headings, lists, quotes, code, links, and images, but lacks native warning boxes, figure captions, and section cross-references. Tools invent extensions, worsening portability.
  • Whitespace carries meaning. Indentation can turn a paragraph into code, while a missing blank line can attach a list to it. These bugs appear only when rendered.
  • Tables are painful. GFM works for three columns of short values; wide tables, multiline or merged cells need HTML or another format.
  • Raw HTML is a security question. HTML in Markdown can let user-submitted content carry scripts, so GitHub filters some tags, and many comment systems sanitize or disable HTML.

For books with indexes and cross-references or strictly structured manuals, AsciiDoc or DocBook may work better. For READMEs, notes, blog posts, issue comments, and most documentation, Markdown’s limits rarely matter.

Common Misconceptions

“Markdown is one standard.” Markdown has multiple flavors. CommonMark defines the core, but note apps, chat tools, and static site generators may differ. If something renders strangely, check the tool’s flavor before assuming a typo.

“Markdown replaces HTML.” Gruber wrote that Markdown is not a replacement for HTML. It handles common cases simply; for anything else, use HTML.

“Pressing Enter starts a new line.” In CommonMark, a line break within a paragraph is usually rendered as a space. A blank line starts a new paragraph. To force a break without starting a paragraph, end the line with a backslash or two spaces.

Some apps treat Enter as a break, which helps explain the confusion.

“The .md file is the finished document.” It’s the source; what readers see depends on the renderer, its flavor, and site styles. The same file may render with different heading anchors, link targets, and code highlighting across sites.

The Model to Keep

Markdown uses plain-text conventions, inspired by email, that renderers convert to HTML. Its human-readable source suits repositories, comments, and docs. Renderers determine the output, and gaps in the original description caused inconsistencies. CommonMark standardized the core; flavors like GFM added requested features.

Think of it as a readable recipe another cook will interpret. Write for source readers, check rendering in the target tool, and use CommonMark when files must travel.

Next Steps

References