Markdown Task List Syntax Complete Guide
What Is a Markdown Task List
When you're writing project docs or taking notes, you often need a checklist — things done, things pending. Markdown task lists (also called checklists or todo lists) do exactly that: they add a toggleable checkbox in front of each list item so you can track progress at a glance.
This syntax was first introduced by GitHub in 2013 as part of GitHub Flavored Markdown (GFM), an extension to the original Markdown spec. It's since been adopted by most mainstream Markdown editors and platforms. That said, the CommonMark forum discussed whether to include task lists in the standard and concluded they'll "always remain an extension" — mainly because their usefulness relies heavily on interactive toggling, which goes beyond simple text-to-HTML conversion.
This article covers the syntax rules, nesting, common pitfalls, and platform compatibility. Whether you're writing a README on GitHub or managing notes in Obsidian, you should be good to go after reading this.
Basic Syntax: How to Write a Task List
Unchecked Tasks
On top of a regular unordered list item, just add [ ] (left bracket + space + right bracket) before the text:
- [ ] Write project documentation
- [ ] Submit code review
- [ ] Deploy to stagingRendered output:
- [ ] Write project documentation
- [ ] Submit code review
- [ ] Deploy to staging
Checked Tasks
Replace the space inside the brackets with a lowercase x to mark it as complete:
- [x] Set up dev environment
- [x] Complete requirements analysis
- [ ] Write unit testsRendered output:
- [x] Set up dev environment
- [x] Complete requirements analysis
- [ ] Write unit tests
Uppercase X works too: - [X] Done. Most renderers treat x and X the same way. My personal habit is to stick with lowercase — it just looks more consistent.
Syntax Details: Every Space Matters
Honestly, this syntax looks simple but the spaces are quite particular. I once missed a single space and the checkbox wouldn't render at all. The correct format is:
List marker (- or * or +) + space + [ + space + ] + space + text contentBreaking it down visually:
- [ ] Task content
↑ ↑ ↑ ↑
│ │ │ └── Right bracket
│ │ └──── Must be a single space (unchecked) or x/X (checked)
│ └────── Left bracket
└──────── List marker, followed by one spaceCommon mistakes to watch for:
- The first space (between the list marker and
[) is required - Inside
[ ]must be exactly one space — not two, not zero - There must be a space between
]and the text
✅ - [ ] Correct format
❌ -[] Missing space, won't render as checkbox
❌ - [ ] Extra space, may not render
❌ - []No space after bracket, renders as plain textI once wrote a README where I forgot the space after ], and the brackets just showed up as literal text. Took me a while to figure out what went wrong.
Using Other List Markers
- isn't your only option. * and + work too:
* [ ] Start with asterisk
+ [ ] Start with plus sign
- [ ] Start with hyphenAll three produce the same result on GitHub, GitLab, and most editors. One thing to note: if you tend to mix these markers in the same document, avoid mixing them within a single task list — some parsers will treat them as separate list blocks.
You can also use task lists inside ordered lists, though this is less common:
1. [ ] First step
2. [x] Second step
3. [ ] Third stepThis works on GitHub, but some editors may only show the numbers without checkboxes.
Nested Task Lists
Task lists support nesting, which is great for breaking down subtasks. The indentation rules are the same as regular nested lists — indent sub-items by 2 to 4 spaces (or one Tab):
- [ ] Project launch
- [x] Purchase domain
- [x] Configure server
- [ ] Performance testing
- [x] Homepage load speed
- [ ] API stress test
- [ ] Go liveRendered output:
- [ ] Project launch
- [x] Purchase domain
- [x] Configure server
- [ ] Performance testing
- [x] Homepage load speed
- [ ] API stress test
- [ ] Go live
You can nest multiple levels, but I'd recommend keeping it under 3 levels for readability. Also, spaces and Tabs both work for indentation, but don't mix them in the same list — that can cause parsing issues.
Adding Formatting Inside Task Lists
Task list items support the same inline formatting as regular text — bold, italic, links, code, etc.:
- [x] Read the [Markdown Guide](https://www.markdownguide.org)
- [ ] Add **error handling** to the `parse()` function
- [ ] Write a tutorial about *GitHub Flavored Markdown*On GitHub, you can even reference issues or PRs inside task list items:
- [ ] Fix login page bug #123
- [x] Merge PR #456
- [ ] Reference https://github.com/org/repo/issues/789GitHub will automatically expand these references to show the issue title and status — super handy for project management.
Checkboxes Inside Tables
This is a problem many people run into — the - [ ] syntax doesn't work inside Markdown tables. The brackets just show up as plain text. That's because table cells use inline parsing, which doesn't support list syntax.
I once tried to add checkboxes to a project progress table and experimented with various approaches. Here are three alternatives:
Option 1: HTML Entities
Use Unicode characters to display checkboxes directly:
| Feature | Status |
|---------|--------|
| User login | ☑ |
| Data export | ☐ |
| Permissions | ☐ |☑ renders as ☑ (checked), ☐ renders as ☐ (unchecked).
Option 2: Emoji
Use emoji characters or shortcodes (supported on GitHub):
| Feature | Status |
|---------|--------|
| User login | :white_check_mark: |
| Data export | :white_large_square: |Option 3: HTML Checkbox
Use raw HTML tags, which work in renderers that support HTML embedding:
| Feature | Status |
|---------|--------|
| User login | <input type="checkbox" checked disabled> |
| Data export | <input type="checkbox" disabled> |Each approach has its use case. HTML entities have the best compatibility, emoji works well on GitHub, and raw HTML is best for editors that support it. Note that all three methods produce static icons — you can't click to toggle them like regular task lists.
Common Issues and Troubleshooting
Checkboxes Not Showing
This is the most common issue. Check in this order:
- Check spaces: Does every position in
- [ ]have the correct space? The one after]is easiest to miss - Check the renderer: Does your editor or platform support GFM task lists? (See the compatibility table below)
- Check indentation: If it's a nested task list, is the indentation consistent? Are you mixing Tabs and spaces?
- Check the list marker: Did you include
-,*, or+before[ ]? Writing just[ ]won't work
Can't Click to Toggle
Task lists have two modes:
- Interactive: Click the checkbox to toggle state (GitHub Issues/PRs, Obsidian, some editors)
- Static display: Shows checkboxes but they're not clickable (GitHub README files, plain Markdown preview)
On GitHub, task lists in Issues and Pull Requests are interactive, but in README.md files they're read-only — to change the status you need to edit the source and change [ ] to [x].
GitHub Tasklist Blocks Are Retired
GitHub previously supported a more advanced tasklist blocks syntax (using ``tasklist code blocks) that could reference other issues as subtasks. This feature was retired in 2024. GitHub now recommends using sub-issues as a replacement. The standard- [ ]` task list syntax is unaffected and continues to work normally.
Multi-Platform Compatibility
Support for task lists varies quite a bit across environments. I've tested several popular platforms and put together this comparison table:
| Platform/Editor | Renders Checkboxes | Interactive Toggle | Notes |
|---|---|---|---|
| GitHub Issues/PR/Comments | ✅ | ✅ | Most complete support, drag-to-reorder |
| GitHub README/Wiki | ✅ | ❌ | Read-only, edit source to change status |
| GitLab | ✅ | ✅ | Similar to GitHub |
| VS Code Built-in Preview | ⚠️ | ❌ | Some versions don't render checkboxes |
| Typora | ✅ | ✅ | Click checkboxes to toggle |
| Obsidian | ✅ | ✅ | Native support, plugins can enhance |
| Jupyter Notebook | ❌ | ❌ | Not supported, shows as plain list |
| Pandoc | ⚠️ | ❌ | Requires specific extensions |
| CSDN | ✅ | ❌ | Renders but interactivity depends on mode |
| Evernote Markdown | ✅ | ✅ | Built-in support, Ctrl+Shift+C shortcut |
This compatibility issue can be quite a headache. My advice: if your content will be published on multiple platforms, confirm the target platform supports it first and have a backup plan ready.
Practical Use Cases
Project README Checklist
Put a task list in your project's README to track pending features or known issues:
## Development Roadmap
- [x] User registration/login
- [x] Article CRUD
- [ ] Comment system
- [ ] Search functionality
- [ ] Mobile responsive designMeeting Notes
Record action items from meetings using task lists, then distribute to the team for tracking:
## 2024-01-15 Product Weekly
- [x] @alice Finalize requirements doc
- [ ] @bob Complete technical review
- [ ] @carol Write test cases
- [ ] @all Code walkthrough by FridayRelease Checklist
Go through the list before each release to avoid missing steps:
## v2.0 Release Checklist
- [x] All unit tests passing
- [x] Code merged to main branch
- [ ] Production database migration
- [ ] Update version number
- [ ] Generate changelog
- [ ] Notify ops teamPersonal Note Management
Use task lists in Obsidian or other note-taking tools for daily planning or learning tracking:
## This Week's Learning Plan
- [x] Complete Rust Chapter 5 exercises
- [ ] Finish "Designing Data-Intensive Applications" Chapter 7
- [ ] Organize WebAssembly study notes
- [ ] Write a Markdown task list tutorial 😄Differences From Related Syntax
If you've read the Markdown List tutorial, you might wonder: what's the difference between a regular list and a task list?
Simply put:
| Feature | Regular List | Task List |
|---|---|---|
| Syntax | - text | - [ ] text |
| Checkbox | No | Yes |
| Interactivity | None | Some platforms support click-to-toggle |
| Purpose | List items | Track completion status |
| Spec | Core Markdown | GFM extension |
Another confusing concept is the Markdown checkbox — it's actually the same syntax as task lists, just a different name. Task list, checkbox list, todo list, and checklist all refer to the same - [ ] syntax.