Tabs and Indentation in Markdown
There is no markdown tab syntax, and indentation changes meaning. Why four spaces becomes a code block, and how to indent text the right way.
Short answer: There is no markdown tab syntax. Pressing Tab in a markdown file inserts a literal tab character, which markdown treats as four columns of indentation — and four columns of indentation at the start of a line creates an indented code block. If your text unexpectedly turned into a grey monospace box, that's why. Remove the leading tab or spaces.
Indentation in markdown is not decoration. It's syntax. Every leading space on a line is meaningful, and the meaning changes depending on how many there are and what came before. This catches out anyone arriving from a word processor, where Tab is just a way to push text to the right.
What Leading Whitespace Actually Means
| Leading whitespace | Meaning |
|---|---|
| 0–3 spaces | Ignored. The line is a normal paragraph, heading, or list. |
| 4+ spaces (or 1 tab) after a blank line | Indented code block |
| 2–3 spaces under a list item | Nested list item |
| 4+ spaces under a list item's content column | Code block inside that list item |
| Trailing 2 spaces at end of line | Hard line break (<br>) |
Three of those five are things people trigger by accident.
Four Spaces Is a Code Block
This is the big one. Original markdown, CommonMark, and GFM all agree: a line indented four or more spaces, following a blank line, is an indented code block.
Normal paragraph.
This line is indented four spaces.
Renders as:
<p>Normal paragraph.</p>
<pre><code>This line is indented four spaces.
</code></pre>
Grey box, monospace font, no markdown formatting applied inside it. This is the correct behavior. It's also why the intuitive move — indenting a line to visually offset it — produces something that looks completely wrong.
How CommonMark counts tabs: a tab advances to the next tab stop of four columns. A tab at the very start of a line therefore counts as four columns and immediately triggers a code block. A tab after two spaces advances to column 4, so <tab> is also four columns.
Indented code blocks are the older of markdown's two code syntaxes and the more fragile one. Use fenced code blocks instead:
```swift
let greeting = "Hello"
```
Fences are unambiguous, they survive being nested inside list items, and they carry a language tag for syntax highlighting. There is no good reason to write a new indented code block in 2026.
Tabs Versus Spaces in Nested Lists
A tab does work for nesting a list:
- Parent item
- Child item (indented with one tab)
CommonMark expands that tab to four columns, which is more than the two columns needed to nest under a - bullet, so it nests correctly. It also works with two spaces, three spaces, or four spaces.
Where tabs get you into trouble is mixing. If some lines use tabs and others use spaces, the file looks aligned in an editor with four-wide tab stops and completely misaligned in an editor with two-wide tab stops — and the parser is going by column count, not by what you see. A list that renders as three clean levels on your machine can render as a code block on someone else's.
The other trap is ordered lists. A 1. item's content starts at column 3, so a nested child needs three columns of indentation. One tab gives you four, which is fine. But a 10. item's content starts at column 4, so a single tab lands exactly at the boundary — and one more column would push the child into code-block territory.
Practical rule: use spaces, and align the child's marker under the first character of the parent's text. Most markdown editors, including OpenMark, insert spaces when you press Tab inside a list and outdent when you press Shift-Tab, so you get the behavior you want without ever writing a tab character. See markdown bullet points and nested lists for the full nesting rules.
You Can't Indent a Paragraph
Markdown has no first-line indent, no left margin, and no equivalent of a word processor's ruler. Indenting a paragraph is a presentation concern, and markdown's position is that presentation belongs in CSS.
If you need it anyway, there are three approaches, in descending order of how well they travel:
Style it in CSS. On your own site, p { text-indent: 2em; } handles every paragraph in the document and keeps the markdown clean. This is the right answer whenever you control the stylesheet.
Use a non-breaking space entity. Four characters push the first line right, and they work almost everywhere including GitHub, because a non-breaking space is a character rather than markup:
This paragraph starts indented.
It's ugly in the source and it doesn't scale to a whole document, but for one pull-quote or one offset line it's the most portable option.
Use inline HTML. <p style="text-indent: 2em"> works in static site generators and desktop editors, but GitHub's sanitizer strips style attributes, so it does nothing in a README.
What you must not do is indent with four spaces. That's the code block, and it's the specific mistake this article exists to prevent.
Blockquotes: The One Real Indentation Syntax
If what you want is offset, quoted-looking text, markdown does have a syntax for it — the blockquote:
> This text is offset from the left margin, with a vertical rule
> beside it in most themes.
Blockquotes nest with additional angle brackets:
> First level
>
> > Second level
> >
> > > Third level
And they contain other markdown, including lists and code blocks:
> **Note**
>
> - Blockquotes can hold lists
> - And inline `code`
Blockquotes are semantic — they produce a <blockquote> element that screen readers announce and that CSS can target. If you're indenting text to set it apart, this is what you actually wanted.
Why Your Text Became a Code Block
The symptom is always the same: grey background, monospace font, formatting inside it ignored. The cause is always leading whitespace. Work through these in order:
- Look for a leading tab. Turn on "show invisibles" in your editor. A single tab at the start of a line is four columns.
- Count the leading spaces. Four or more after a blank line is a code block.
- Check the parent list item's content column. Inside a list, the threshold isn't four spaces from the left margin — it's four spaces past where the parent item's text begins.
- Check for mixed tabs and spaces. Two spaces followed by a tab is four columns, not three.
- Check what precedes the line. Indented code blocks require a preceding blank line. If the line is a lazy continuation of the paragraph above, the indentation is simply ignored — which is why the same indented line behaves differently depending on what's above it.
The fastest way to diagnose this is to see the source and the rendered output at the same time. OpenMark puts raw markdown with syntax coloring in Markdown view and the rendered result in Document view, so a stray tab shows up as a code block the moment you switch.
For a fast lookup of the rest of the syntax, see the markdown quick reference. If you're writing documentation with lots of code samples, markdown for developers covers fenced blocks and language tags in more depth, and escaping special characters in markdown handles the other class of "why did my text render like that" problems.
Download OpenMark → — $9.99, one-time, native macOS. Tab and Shift-Tab indent list items properly, and Document view shows you instantly when indentation became a code block.