Markdown is a plain-text syntax that turns simple punctuation into formatted HTML — a hash for a heading, asterisks for emphasis, hyphens for a list — so you can write structured documents without tags and read them comfortably even before they are rendered. It is deliberately small, which makes it quick to learn, but a handful of whitespace rules and differences between flavours cause most of the confusion people hit. This guide covers the core syntax and the edge cases that actually bite.
How do headings and paragraphs work?
Headings use one to six hash signs at the start of a line, and paragraphs are simply blocks of text separated by a blank line. The number of hashes sets the level, mirroring HTML’s h1 through h6:
# Heading level 1
## Heading level 2
### Heading level 3
A paragraph is just text. Leave a blank line
between blocks to start a new paragraph.
The blank line is doing real work. Two lines of text with no blank line between them typically collapse into a single paragraph, with the line break ignored. This is the most common first surprise: you press Enter once expecting a new line and get a continuous sentence instead. To force a line break within a paragraph, end the first line with two trailing spaces, or in many flavours a backslash at the line end. To start a genuinely new block, use the blank line.
How do I write emphasis, lists and links?
Wrap text in single asterisks or underscores for italic, double for bold, and start each list item with a marker; links put the text in square brackets and the URL in parentheses. These are the everyday building blocks:
*italic* or _italic_
**bold** or __bold__
***bold italic***
- Unordered item (also works with * or +)
- Another item
- Indented sub-item (indent under the parent)
1. Ordered item
2. Ordered item
[link text](/some/path)
Ordered lists renumber automatically in most processors, so you can write 1. for every item and still get 1, 2, 3 in the output — handy when reordering. Nested lists depend on indentation, and the amount of indent that “counts” varies between processors, which is a frequent source of a sub-list that stubbornly refuses to nest. When it misbehaves, indenting the child by the same width as the parent’s marker and following space is the reliable fix.
How do I format code in Markdown?
Wrap inline code in single backticks, and wrap a whole block in a fence of three backticks on their own lines, optionally naming the language after the opening fence. Inline code is for a variable or a short snippet mid-sentence; fenced blocks preserve whitespace and are ideal for multi-line samples:
Use the `map()` method for inline code.
```js
function greet(name) {
return `Hello, ${name}`;
}
```
The language label after the opening fence (here js) enables syntax highlighting in processors that support it. The older alternative is an indented code block: indent every line by four spaces. Fenced blocks are almost always preferable because they do not require indenting each line and they let you declare the language. A common mistake is forgetting that inside a fenced block Markdown formatting is turned off entirely, so asterisks and hashes there render literally — which is exactly what you want for code.
Why do tables and other features differ between tools?
Because Markdown has no single official specification for many features, so extended flavours add their own syntax and the same text can render differently depending on the processor. The original Markdown was intentionally minimal and did not define tables, fenced code blocks, task lists, or strikethrough at all. Later flavours — the widely used GitHub Flavored Markdown among them — added these, and a specification effort called CommonMark tightened the core rules to reduce ambiguity.
| Feature | Original Markdown | Common extended flavours |
|---|---|---|
| Tables | Not supported | Pipe-and-hyphen syntax |
| Fenced code blocks | Not supported | Triple backtick fences |
| Task lists | Not supported | – [ ] and – [x] |
| Strikethrough | Not supported | ~~text~~ |
A table in the extended flavours uses pipes for columns and a row of hyphens to separate the header, with colons to set alignment:
| Name | Role |
|:------|---------:|
| Ada | Engineer |
| Grace | Admiral |
The colon placement in the separator row controls alignment: left, right, or centred. Because these features are extensions, a document that renders perfectly in one tool may show raw pipes in another that does not support tables. When formatting looks wrong, checking which flavour the target supports is the first thing to rule out. A client-side Markdown preview lets you see exactly how your text renders as you type, entirely in the browser, which is the fastest way to catch a whitespace or flavour issue before you publish.
How do I escape special characters?
Put a backslash before a character to render it literally instead of as Markdown syntax. Because Markdown assigns meaning to characters like *, _, #, `, [ and >, you sometimes need to show one as plain text. Escaping tells the processor to treat the next character as ordinary:
*not italic* renders as *not italic*
1. not a list renders as 1. not a list
# not a heading renders as # not a heading
The other escape route is context: characters inside inline code or a fenced block are already literal, so a lone asterisk in a code span needs no backslash. Escaping matters most in running prose where a stray underscore in a file name or an asterisk in a maths expression would otherwise trigger unwanted emphasis. If you find yourself escaping many characters in a run of text, wrapping the whole span in backticks is often cleaner.
Can I mix in raw HTML, and should I?
Most Markdown processors let you drop raw HTML directly into the document for anything Markdown cannot express, though whether that HTML survives depends on the processor’s sanitisation. Need a specific attribute, a figure with a caption, or a construct Markdown lacks? You can write the HTML tags inline and the processor passes them through. This escape hatch is part of why Markdown stays small: it does not need to cover every case because HTML is always available underneath.
Two more constructs round out everyday Markdown. Blockquotes start each line with a > and can nest by adding more of them, which is handy for quoting replies or setting off a note. Horizontal rules are three or more hyphens, asterisks, or underscores alone on a line, giving a thematic break between sections:
> A quoted line.
>> A nested quote inside it.
---
A subtle trap with the hyphen rule: three hyphens directly beneath a line of text can be interpreted as a setext heading underline rather than a horizontal rule, turning the line above into a heading unexpectedly. Leaving a blank line before the hyphens avoids the ambiguity. These small gotchas are exactly the kind of thing a live preview surfaces instantly — you see the wrong render and fix the spacing in seconds, rather than discovering it after publishing.
The caveat with raw HTML is safety and portability. Systems that render user-supplied Markdown often sanitise or strip HTML to prevent script injection, so raw tags may be removed or neutralised depending on where the text is published. For your own documents that is rarely an issue; for content that others will render, lean on standard Markdown where you can and reserve raw HTML for the genuine gaps. Kept in that spirit, Markdown gives you clean, readable source that renders to solid HTML — and the preview-as-you-type loop is what turns the handful of whitespace and flavour rules from surprises into muscle memory.