The Markdown Guide
Markdown is a plain-text format for writing formatted documents. You type a few unobtrusive characters — # for a heading, **bold**, - item for a list — and a renderer turns the result into headings, bold text, and lists. This guide covers the full markdown syntax, the rules, an at-a-glance cheat sheet, and what makes a .md file different from HTML or Word.
What is Markdown?
Markdown is a lightweight markup language created by John Gruber and Aaron Swartz in 2004. The idea was to design a plain-text format that reads naturally as-is — so the source of a document already looks like a document — and that converts cleanly to HTML. A file written in this format is saved with the .md extension (sometimes .markdown), and any text editor can open it.
The original Markdown spec was deliberately small. Over time the ecosystem fragmented: CommonMark formalised the parsing rules, and GFM (GitHub-Flavored Markdown) added the parts most people now consider standard — tables, fenced code blocks with language hints, task lists, strikethrough, and autolinks. When someone says "Markdown" today, they usually mean GFM, because GitHub, Reddit, Discord, Obsidian, and most documentation tools render that dialect. mdstill outputs GFM-compatible Markdown by default.
You will encounter md files in README files on GitHub, notes in Obsidian, static-site sources (Jekyll, Hugo, Astro, Docusaurus), Jupyter notebook cells, and as the native output format of LLMs like ChatGPT and Claude. If you already have a .md file and just want to view it rendered, see how to open a .md file.
Headings
Headings start with one to six # characters, followed by a space and the heading text. One # is an H1, two is an H2, all the way to six for H6. Put a blank line before each heading to avoid the next line being read as part of a paragraph.
# H1 — page title
## H2 — section
### H3 — subsection
#### H4
##### H5
###### H6H1 — page title
H2 — section
H3 — subsection
H4
H5
H6
Markdown rules: pick one H1 per document (treat it as the page title) and use H2/H3 for the structure underneath. Skipping levels — H2 directly to H4 — works syntactically but hurts accessibility and document outlines.
Emphasis: bold, italic, strikethrough
Wrap text in delimiters: one asterisk or underscore for italic, two for bold, three for both, and two tildes (a GFM extension) for strikethrough.
*italic* or _italic_
**bold** or __bold__
***bold italic***
~~strikethrough~~ (GFM)italic or italic
bold or bold
bold italicstrikethrough (GFM)
A common gotcha: snake_case_words can accidentally turn into italic. Most modern parsers (CommonMark, GFM) ignore underscores inside words, but if a renderer is picky, use asterisks for emphasis.
Lists in Markdown
A list in markdown is either unordered (each item starts with -, *, or +) or ordered (each item starts with a number followed by .). Indent by two or four spaces to nest.
- Apples
- Pears
- Bartlett
- Anjou
- Plums
1. Wake up
2. Write markdown
3. Push to GitHub- Apples
- Pears
- Bartlett
- Anjou
- Plums
- Wake up
- Write markdown
- Push to GitHub
The actual numbers in an ordered list do not matter — every parser renumbers them. You can write 1. 1. 1. and the renderer will output 1, 2, 3. That makes it easy to reorder items without renumbering.
Links and images
A link is [text](url). An image is the same syntax with a leading !. Autolinks wrap a bare URL in angle brackets, and reference-style links let you put the URL once at the bottom of the document and reuse a label.
[mdstill homepage](https://mdstill.com)

<https://github.com>
[reference link][gh]
[gh]: https://github.com "GitHub"Markdown code block
For inline code, wrap text in single backticks. A markdown code block is either four-space indented or, more commonly, fenced with three backticks. After the opening fence you can add a language hint — ```python — and renderers that support syntax highlighting will use it.
Inline `console.log('hi')` works.
```python
def greet(name):
print(f"Hello, {name}")
```Inline console.log('hi') works.
def greet(name):
print(f"Hello, {name}")Use fenced code blocks (three backticks) rather than indented ones — they preserve language hints, they round-trip through more tools, and they do not get confused with adjacent lists.
Blockquotes
Prefix a line with > for a blockquote. Stack them for nested quotes. A blockquote can contain other Markdown — paragraphs, lists, even code.
> Writing is thinking.
>
> > Reading is thinking with someone else's brain.
> A quote with a **bold** word and a list:
> - first
> - secondWriting is thinking.
Reading is thinking with someone else's brain.
A quote with a bold word and a list:
- first
- second
Markdown table syntax
Markdown table syntax is a GFM extension: pipes | separate columns and a row of dashes underneath the header sets alignment. Add a colon to the dashes to align left (:--), right (--:), or centre (:--:).
| Format | Extension | Binary? |
| :----- | :-------: | ------: |
| Markdown | .md | No |
| Word | .docx | Yes |
| PDF | .pdf | Yes || Format | Extension | Binary? |
|---|---|---|
| Markdown | .md | No |
| Word | .docx | Yes |
| Yes |
Outer pipes are optional but make the source easier to read. The separator row must contain at least three dashes per column. CommonMark itself does not specify tables — they are GFM.
Task lists and GFM extras
GitHub-Flavored Markdown adds a handful of useful features on top of CommonMark: task lists (checkboxes), strikethrough, autolinked URLs, and tables (covered above). Task lists are list items where the marker is replaced with - [ ] for an unchecked box or - [x] for a checked one.
- [x] Write the guide
- [x] Add a cheat sheet
- [ ] Get hit by Google's next core update
- [ ] Profit- Write the guide
- Add a cheat sheet
- Get hit by Google's next core update
- Profit
Horizontal rules
Three or more dashes, asterisks, or underscores on a line by themselves render as a horizontal rule. Surround them with blank lines so they are not mistaken for a heading underline.
Above the line.
---
Below the line.Above the line.
Below the line.
Escaping characters
To use a Markdown control character literally — when you want a real asterisk, not italics — precede it with a backslash. The escapable characters are roughly the ones the syntax uses: \ ` * _ {} [] () # + - . ! |.
\*not italic\*
1\. Not a list item.
Use \` for a literal backtick.*not italic*
1. Not a list item.
Use ` for a literal backtick.
Markdown vs HTML
Markdown compiles to HTML. The two are not competitors — they are layers. Markdown is what you write; HTML is what the renderer emits. The reason Markdown exists is that HTML is verbose to type: <strong>bold</strong> vs **bold**. For 80% of formatting needs, Markdown is faster, easier to read in raw form, and easier to diff in version control.
Use Markdown when you are writing prose — docs, READMEs, notes, blog posts, LLM prompts. Use HTML directly when you need something Markdown does not cover — semantic elements like <details>, custom id / class attributes, embedded media. Most Markdown parsers let you mix HTML inline, so you rarely have to choose.
If you have an HTML document you want to convert in the other direction, see HTML to Markdown.
Markdown cheat sheet
Every common element in one table — markdown syntax on the left, rendered result on the right. Bookmark this section as your quick-reference markdown cheat sheet.
| Element | Markdown | Rendered |
|---|---|---|
| H1 | # Heading | Heading |
| H2 | ## Heading | Heading |
| H3 | ### Heading | Heading |
| Bold | **bold** | bold |
| Italic | *italic* | italic |
| Bold italic | ***both*** | both |
| Strikethrough | ~~gone~~ | |
| Inline code | `code()` | code() |
| Code block | ```
code
``` | fenced block |
| Link | [text](url) | text |
| Image |  | (renders an image) |
| Autolink | <https://x.com> | https://x.com |
| Unordered list | - item | • item |
| Ordered list | 1. item | 1. item |
| Task list | - [x] done | done |
| Blockquote | > quoted | quoted |
| Horizontal rule | --- | |
| Table | | a | b |
| - | - | | (GFM pipe table) |
| Escape | \*literal\* | *literal* |
Markdown flavors: CommonMark, GFM, MultiMarkdown
The original Markdown spec from 2004 was ambiguous in enough edge cases that every parser made its own decisions. Three main dialects emerged.
- CommonMark — a rigorous re-specification published in 2014 that pins down the parser behaviour for every corner case. It is the foundation modern parsers build on.
- GFM (GitHub-Flavored Markdown) — CommonMark plus tables, task lists, strikethrough, autolinks, and disallowed raw HTML. This is the dialect rendered by GitHub, Reddit, Discord, and most documentation tools, and it is what people usually mean when they say "Markdown".
- MultiMarkdown — a separate extension set with footnotes, citations, math, and metadata blocks. Niche but useful for academic writing.
mdstill produces GFM-compatible Markdown by default — tables, fenced code blocks with language hints, task lists where present in the source. That is the dialect every modern reader expects.
What can you do with a .md file?
Once you have a .md file, you can view it rendered, edit it in any text editor, or convert it to other formats for sharing. mdstill handles both directions:
- Open a .md fileView any markdown file rendered in the browser.
- Markdown to PDFExport your .md as a shareable PDF.
- Markdown to WordConvert .md to .docx with real headings and tables.
- Markdown to HTMLGet clean HTML output from your .md source.
- PDF to MarkdownExtract clean .md from any PDF.
- Convert anything to MarkdownDrop in DOCX, PPTX, XLSX, EPUB, HTML, and more.