Markdown Tab and Indent: What Whitespace Actually Does (2026)
TL;DR: A markdown tab is a tab stop of four columns, not a substitution of four spaces. Four or more spaces after a blank line becomes a code block — but inside a list item the threshold is the item's content column plus four, so under
- parentyou need six. Three spaces of indentation is always safe.
Most guides to the markdown tab tell you a tab equals four spaces, and that four spaces makes a code block. Both are wrong often enough to break real documents, and the specification says so directly. Here are the actual rules, each traced to its section of CommonMark 0.31.2 and checked against how GitHub renders it. If you read a lot of .md files on macOS, MacMD Viewer shows you the rendered result instead of making you reason about it.
Throughout, → marks a literal tab character. That is the convention the CommonMark spec uses, because a real tab is invisible in a code block and invisible bugs are the problem here. For syntax this page does not cover, see the markdown cheat sheet.
What Does a Markdown Tab Actually Do?
A tab is never converted to spaces. CommonMark section 2.2 defines it as a tab stop: where indentation defines block structure, a tab advances to the next column that is a multiple of four. How much whitespace it contributes depends on where it sits in the line.
The spec states it in one sentence:
"Tabs in lines are not expanded to spaces. However, in contexts where spaces help to define block structure, tabs behave as if they were replaced by spaces with a tab stop of 4 characters."
So a tab is worth four columns only at the start of a line. Section 2.2 shows the case that catches people:
>→→fooThe > sits in column 1, so the first tab only reaches the column-4 tab stop — three columns, not four. One of those three counts as the optional space after >, leaving two. The second tab adds four more, for six columns of indentation inside the blockquote. The result is a blockquote containing a code block indented by two spaces, not a blockquote containing foo. That is the arithmetic governing every tab placed after a block marker.
The other half of the rule: a tab inside content stays a tab. Put one mid-line in a code block and it passes through to the output unchanged.
Should You Use Tabs or Spaces in Markdown?
Use spaces for anything that defines structure. Tabs are perfectly legal — section 5.2 allows a tab as the separator after a list marker, so -→foo is a valid list item — but a tab's column value depends on its position, which makes it the one whitespace character you cannot count by eye.
Three rules cover almost every case:
- Indent structure with spaces. Nested lists, continuation paragraphs, code blocks inside list items.
- Never mix a tab and spaces in the same indent. The failure mode is silent (see below).
- Keep incidental indentation at three spaces or fewer.
- itemis still a list item;- itemis a code block containing that text.
If your editor inserts a tab when you press Tab, that is an editor setting, not a Markdown rule. Configure it to insert spaces in .md files and the problem disappears.
The Four-Space Code Block Trap
Four or more spaces of indentation after a blank line creates an indented code block. This is CommonMark section 4.4, and it is the single most common way a Markdown document breaks: a paragraph you indented for readability renders as grey monospace with a scroll bar.
A normal paragraph.
This line was indented four spaces.The second block renders as code on GitHub, on the CommonMark reference parser, and in pandoc alike. A single leading tab does the same thing, reaching column four from the start of the line.
Two details make this survivable. Three spaces is safe: the same text indented three spaces stays a paragraph. And section 4.4 says an indented code block "cannot interrupt a paragraph", so the blank line above is load-bearing — without it, the indented line joins the paragraph instead.
The Markdown Guide's advice is blunt and correct: unless the paragraph is inside a list, do not indent paragraphs at all.
Is "Four Spaces Means Code Block" True Inside a List?
No, and this is where most pages get it wrong. Inside a list item the threshold is not four spaces from the left margin — it is four spaces past the item's content column. Under - parent, whose content column is 2, a code block needs six spaces. Four spaces produces an ordinary paragraph.
- parent
continuation indented four spacesThat renders as a paragraph inside the list item. Add two more spaces and it flips:
- parent
six spacesNow it is a code block. The spec resolves the ambiguity itself, in section 4.4:
"If there is any ambiguity between an interpretation of indentation as a code block and as indicating that material belongs to a list item, the list item interpretation takes precedence."
A tab-indented continuation under - parent is also a paragraph, not code: the tab reaches column 4, still short of the 6 required. That is why a continuation paragraph that looked fine inside a list turns into code the moment you paste it outside one.
How Much Indentation Does a Nested List Need?
As much as the parent marker occupies, plus the spaces after it. Section 5.2 rule 1 defines the required indent as W + N: the width of the list marker plus the 1 to 4 spaces following it. That is 2 for - , 3 for 1. , and 4 for 10. . There is no universal "2 spaces" or "4 spaces" rule, which is why so much advice about it conflicts.
Rendered through GitHub and the CommonMark reference parser, the arithmetic is visible:
| Input | Result |
|---|---|
- parent then - child (2 spaces) | Nested sublist |
1. parent then 2. child (2 spaces) | Flat — two siblings in one list |
1. parent then 1. child (3 spaces) | Nested sublist |
10. parent then 1. child (3 spaces) | Flat |
10. parent then 1. child (4 spaces) | Nested sublist |
Two spaces nests a bullet and fails an ordered item, because 1. is three characters wide. GitHub's own documentation gives two methods rather than one number: in a monospaced editor, align the child marker under the first character of the parent's text; in the comment editor, count the characters before the parent's content and type that many spaces — for 100. First list item, "a minimum of five spaces, since there are five characters". Both are W + N, one measured by eye and one counted. For the full set of nesting patterns, see the markdown nested lists guide; for lists in general, the markdown lists guide.
Mixing Tabs and Spaces Flattens Nesting Silently
A tab followed by spaces produces neither a sublist nor an error. It produces a single list item with your child marker sitting inside it as literal text, and nothing signals that anything went wrong.
- parent
→ - childOn GitHub and in the CommonMark reference parser, that renders as one list item containing the text - child. The tab jumps to column 4, the two spaces take it to column 6, which would be indented code. But an indented code block cannot interrupt a paragraph, so the line falls through to lazy paragraph continuation instead. No sublist, no code block, no warning.
This is the first thing I check when a list renders flat and the source looks correct. Pick one whitespace character per file, and if you inherit a document that already mixes them, turn on whitespace rendering in your editor before touching the indentation.
Do Tabs Break Markdown Tables?
A tab before the first pipe destroys a table completely. Tabs used as padding between pipes are harmless, and a tab inside cell text survives into the HTML but disappears visually. Three cases, three different outcomes.
A leading tab on the header row is fatal:
→| a | b |
| --- | --- |
| c | d |GitHub renders the first row as a code block and the remaining two as a plain paragraph. The table is gone. Indent all three rows by four spaces and the whole table becomes one code block instead.
Padding tabs are safe. Written as | a→|→b |, the cells come out clean as a and b. GitHub and CommonMark parsers both trim tab padding, even though the GFM table specification only promises to trim spaces.
A tab inside cell text is the ambiguous case. | a→b | c | puts a literal tab in the cell; it survives into the HTML, then the browser collapses it to a single space like any other run of whitespace. Not lost, just invisible. For column alignment, use spaces or a generator; the markdown table guide covers the alignment syntax.
How Do You Indent a Paragraph in Markdown?
Markdown has no paragraph-indent syntax, and leading spaces are already taken by the code block rule. The fallback is an HTML entity: for a normal space width,   for an em-width gap. It has to be written in escaped entity form.
This paragraph starts indented.The trap is that the entity and the character are not interchangeable. Written as entities, the four non-breaking spaces survive on GitHub and in the CommonMark reference parser. Paste four literal U+00A0 characters instead and GitHub keeps them while the reference parser strips them, so the same file renders two ways depending on the tool.
The entities available are (U+00A0),   (U+2002),   (U+2003), and   (U+2009). The Markdown Guide, which documents this hack, says it "should probably be your option of last resort as it can get awkward". Its first recommendation is an editor with real indentation settings, and I agree.
One related non-rule: a trailing tab is not a hard line break. Two trailing spaces produce a <br />; a trailing tab produces nothing and stays literal. The markdown line break guide covers the four methods that do work.
Platform and Editor Behavior, Side by Side
Two different questions get confused here: what the Tab key does in the editor, and what the renderer does with the indentation once it is in the file. They have different answers on nearly every platform.
What the Tab key does:
| Platform | Tab key behavior |
|---|---|
| GitHub — web-based editor | Indents/dedents selected lines (documented) |
| GitHub — comment, issue, PR box | Not documented as indenting; moves focus out of the text area (open community request) |
| Obsidian | Indents or unindents selected list items (documented) |
| Typora | Indent shortcut, alongside Command+[ on macOS |
| VS Code | No Markdown-specific behavior — inserts 4 spaces by default, adjusted by editor.detectIndentation |
| Slack, Discord, Reddit | No Tab-key behavior documented |
What the renderer does with indentation:
| Platform | Nested lists | 4-space indented code blocks |
|---|---|---|
| GitHub | CommonMark W + N | Yes |
| GitLab | CommonMark-based, same rule | Yes — "indent it four or more spaces" |
| Reddit (new) | Sublists shown with 3 spaces in the official guide | Yes, plus fences |
| Reddit (old) | Same | Indented blocks only — fences do not work |
| Discord | 2 spaces, documented literally | No — backticks only |
| Slack | No list syntax at all in mrkdwn | No — triple backticks only |
| Obsidian | Indent one or more items; no count documented | Yes — Tab or 4 spaces |
| Typora | Not documented | No — fences only |
Two footnotes explain a lot of confusion here. The published GitHub Flavored Markdown spec is version 0.29-gfm, based on CommonMark 0.29 from 2019, five years behind the current 0.31.2. Its Tabs section differs by one word: 0.29 says tabs matter "in contexts where whitespace helps to define block structure", 0.31.2 says "where spaces help". The behavior is unchanged — only the phrasing was tightened, to make clear the measure is columns — but cite the version if you cite a section number. And GitHub renders comments and .md files differently: in a comment box every newline becomes a <br>, in a repository file it does not. That accounts for a lot of "it worked in the issue but not in the README".
How Do You Preview Markdown Indentation on Mac?
macOS ships no Markdown renderer, so TextEdit shows your indentation as raw text and gives you no way to tell a 4-space paragraph from a 6-space code block. Three options, from free to purpose-built.
VS Code — open the .md file and press Cmd+Shift+V for the built-in preview. It uses a CommonMark-compatible renderer, and the editor.renderWhitespace setting — the View: Toggle Render Whitespace command in the palette — shows tabs and spaces in the source pane at the same time.
MacMD Viewer — the native SwiftUI app I build. It parses with swift-markdown on top of cmark-gfm, so indentation resolves the way this article describes: QuickLook preview in Finder (press Space on any .md file), Mermaid diagrams, syntax highlighting, 12 document themes, and live reload when the file changes on disk. Set it as your default .md handler and double-clicking opens a rendered view. Download MacMD Viewer, $19.99 one-time.
Terminal with Glow — brew install glow, then glow README.md renders Markdown in the terminal.
For a wider comparison, see the best markdown viewer guide.
Frequently Asked Questions
Does a tab equal four spaces in Markdown?
No. CommonMark 0.31.2 section 2.2 states that tabs are not expanded to spaces. A tab advances to the next multiple-of-four column, so a tab in the first column supplies four columns while a tab placed after two characters supplies only two. Inside content, a tab stays a literal tab.
How many spaces do you need to indent a nested list in Markdown?
There is no fixed number. Section 5.2 defines the required indent as W + N, the width of the parent marker plus the spaces after it: 2 for - , 3 for 1. , and 4 for 10. . Two spaces nests a bullet but leaves an ordered item flat, because 1. is three characters wide.
Why did my indented text become a code block?
Four or more spaces of indentation after a blank line creates an indented code block (section 4.4). Three spaces is always safe. Inside a list item the threshold is higher — the item's content column plus four — so under - parent you need six spaces before the text is treated as code.
Can I use the Tab key to indent Markdown lists?
That depends on the editor, not on Markdown. GitHub documents Tab and Shift+Tab for indenting only in its web-based editor; in a comment box, Tab moves focus out of the field. Obsidian and Typora both document Tab as an indent shortcut. VS Code inserts spaces and does not nest list items for you.
Do tabs work inside Markdown tables?
Padding tabs between pipes are trimmed by GitHub and by CommonMark parsers, so tab-aligned source is safe. A tab inside cell text survives into the HTML but collapses to a single space when the browser renders it. A tab before the first pipe is fatal: the header row becomes a code block and the table disappears.
How do you indent a paragraph in Markdown?
Markdown has no paragraph-indent syntax, and leading spaces are claimed by the code block rule. The portable workaround is the escaped entity form: for a space-width gap,   for an em-width one. Pasting literal non-breaking space characters is not portable, since GitHub keeps them and the CommonMark reference parser strips them.
Content licensed under CC BY 4.0. Cite with attribution to MacMD Viewer.