A task list is an ordinary bulleted list where each item starts with a pair of square brackets. Empty brackets are an unchecked box, an x between them is a checked one. It is the syntax behind every to-do list, every pull-request checklist and every project README that tracks progress.
- [x] Write the draft
- [ ] Edit it
- [ ] Export to PDF
- [x] Choose the margins
- [ ] Add page numbers
- [ ] Send it- [x] Write the draft
- [ ] Edit it
- [ ] Export to PDF
- [x] Choose the margins
- [ ] Add page numbers
- [ ] Send it
The syntax
- [ ] Not done
- [x] Done- [ ] Not done
- [x] Done
Three things have to be right:
- It must be a list item. The
-(or*, or+) comes first. Brackets on their own line are just brackets. - A space inside the empty box.
- []is not a checkbox;- [ ]is. - A space after the closing bracket.
- [x]Donefails,- [x] Doneworks.
Capital X works as well as lowercase in most renderers, but lowercase is the convention.
Where the boxes are clickable
The checkbox is rendered as a real <input type="checkbox">, and whether you can click it depends entirely on where the document is displayed:
- GitHub and GitLab issues, pull requests and README files: clickable, and ticking a box edits the underlying Markdown for everyone.
- Most static site generators and previews: rendered but disabled — a picture of a checkbox.
- Note-taking and editor apps: usually clickable, updating the file as you go.
If a box refuses to respond, the renderer has disabled it. That is a deliberate choice, not a bug in your syntax.
Nesting
Task lists nest exactly like ordinary lists: two spaces per level.
- [ ] Ship the release
- [x] Write the changelog
- [ ] Take screenshots
- [ ] Submit for review- [ ] Ship the release
- [x] Write the changelog
- [ ] Take screenshots
- [ ] Submit for review
Parent boxes do not tick themselves when their children are done. Nothing in Markdown computes progress — it is a text format, not a project manager.
Mixing with other formatting
Everything you can put in a list item works inside a task too:
- [x] Read the [guide to lists](/markdown-lists)
- [ ] Run `npm run build`
- [ ] Fix the **critical** bug
- [ ] Ask someone about ~~the old approach~~ the new one- [x] Read the guide to lists
- [ ] Run
npm run build - [ ] Fix the critical bug
- [ ] Ask someone about
the old approachthe new one
Keeping the list tight
A blank line between items turns a tight list into a loose one, and every task gets its own paragraph’s worth of spacing. On a checklist of twenty items that looks broken. Keep the lines adjacent — see tight and loose lists.
Common mistakes
Missing the space inside the brackets. - [] renders as literal brackets. It needs to be - [ ].
Forgetting the list marker. [ ] Task is not a task list, it is a paragraph beginning with square brackets.
No blank line before the list. A task list that starts directly under a paragraph gets absorbed into it, exactly as any other list does.
Expecting them everywhere. Task lists are a GitHub Flavored Markdown extension. They are near-universal in modern tools, but the original 2004 Markdown has no concept of them.
Expecting a progress count. 3/8 done is something the tool around the file computes, not something the Markdown expresses.
FAQ
How do I make a checkbox in Markdown?
Start a list item with a pair of brackets: - [ ] for unchecked and - [x] for checked. The space inside the empty brackets is required.
Why is my Markdown checkbox not clickable?
Because the renderer disabled it. GitHub, GitLab and most editor apps let you click a box and write the change back to the file; static site generators and read-only previews usually render the box as a disabled input, so it is only a picture of a checkbox.
Can I nest task lists in Markdown?
Yes. Indent by two spaces per level, exactly as with a normal list. Checking every child does not automatically check the parent — nothing in Markdown tracks that.
Do task lists work everywhere?
Almost. They come from GitHub Flavored Markdown rather than the original spec, so a very old or deliberately minimal parser will render them as literal brackets. Every mainstream editor and platform supports them.
What is the difference between - [x] and - [X]?
Nothing in practice — both render as a checked box in essentially every parser. Lowercase is the convention.