# MD010 - Use spaces instead of tabs
Aliases: `no-hard-tabs`
## What this rule does
Replaces tab characters with spaces to ensure consistent indentation across all editors and platforms.
## Why this matters
- **Consistency**: Tabs display differently in different editors (2, 4, or 8 spaces wide)
- **Team collaboration**: Mixed tabs and spaces create confusing indentation and merge conflicts
- **Tool compatibility**: Many Markdown tools and platforms expect spaces for proper formatting
- **Readability**: Consistent spacing makes documents easier to read and maintain
## Examples
### ✅ Correct
```markdown
* Shopping list
* Fruits
* Apples
* Bananas
* Vegetables
* Carrots
* Broccoli
Remember to check for freshness!
```
### ❌ Incorrect
> `→` represents a hard tab character.
```markdown
* Shopping list
→* Fruits
→→* Apples
→→* Bananas
→* Vegetables
→→* Carrots
→→* Broccoli
→Remember to check for freshness!
```
### 🔧 Fixed
```markdown
* Shopping list
* Fruits
* Apples
* Bananas
* Vegetables
* Carrots
* Broccoli
Remember to check for freshness!
```
## Configuration
```toml
[MD010]
spaces-per-tab = 4 # Number of spaces to replace each tab with (default: 4)
code-blocks = false # Skip tabs inside code blocks (default: false)
ignore-code-languages = ["makefile"] # Fence languages to never flag (default: none)
```
### Configuration options explained
- `spaces-per-tab`: How many spaces to use when replacing each tab character.
- `code-blocks`: When `false` (default), hard tabs inside fenced and indented
code blocks are skipped - tabs are often required there (Makefiles, Go) and
rewriting them would corrupt examples. Set to `true` for markdownlint-parity
behavior that flags tabs everywhere, including code blocks.
- `ignore-code-languages`: Fence languages whose tabs are never reported, so you
can flag tabs in code blocks generally while keeping the languages that need
them. The language is the first word of the info string, matched
case-insensitively, so ```` ```makefile title="Makefile" ```` matches
`makefile`. This only has an effect when `code-blocks = true`, since otherwise
every code block is already skipped. An indented code block has no info
string, so it can never match; use `code-blocks = false` to skip those.
Flavors that write the language somewhere other than the first word are read
on their own terms:
| Flavor | Fence | Matches |
|--------|-------|---------|
| `pandoc`, `quarto` | ```` ```{#id .makefile} ```` | `makefile` (first `.class`) |
| `quarto` | ```` ```{r, echo=FALSE} ```` | `r` (the chunk engine) |
| `azure_devops` | `::: mermaid` | `mermaid` (the colon fence language) |
> **Behavior change:** Earlier versions skipped tabs in fenced code blocks
> while still flagging indented ones. MD010 now treats both code-block types
> consistently and, by default, does not flag tabs in either. Note that a
> document whose content starts with a tab-indented line is a CommonMark
> indented code block, so leading tabs there are no longer flagged by default.
> Set `code-blocks = true` to flag tabs in all code blocks.
## Automatic fixes
This rule automatically replaces each tab character with the configured number of spaces (default: 4). This ensures your document looks the same in every editor.
## Learn more
- [CommonMark specification](https://spec.commonmark.org/0.31.2/#tabs) - Technical details about tab handling
## Related rules
- [MD009](md009.md) - Remove trailing spaces
- [MD007](md007.md) - Keep list indentation consistent
- [MD005](md005.md) - Keep list indentation consistent