Nested Lists

A nested list lets one item carry a second layer of detail: a feature and its sub-features, a step and the sub-steps inside it, a category and the entries under it. Markdown has no syntax for nesting at all. There is no nested keyword, no closing tag, no wrapper element. The hierarchy exists in exactly one place — the whitespace at the start of the line — and that makes the indentation rules the only thing you really have to learn on this page.

The rule is narrower than the folklore suggests and wider than the four spaces that many tutorials insist on. What decides whether a line is a child is not the number of spaces you type but the column where the parent item’s text starts, and that column is the width of the parent’s marker. Two spaces and four spaces both work, three spaces work too, and so does any value inside a range whose upper end is a hard boundary: four spaces past the content column and the parser stops reading a list and starts reading a code block.

Indentation is the only hierarchy

A child list is a list that is indented into the item above it:

- Level one
  - Level two
    - Level three
- Another item
<ul>
<li>Level one
<ul>
<li>Level two
<ul>
<li>Level three</li>
</ul>
</li>
</ul>
</li>
<li>Another item</li>
</ul>

The child list sits inside the <li> of its parent, and the last item returns to the top level because its indentation matches the first one. Nothing in the source marks the end of a child list; the indentation alone decides where each level begins and ends.

Two spaces or four

The indentation a child needs is measured from the width of the parent’s marker, not from a fixed number:

Parent markerMarker widthChild indent
- plus a space2 columns2 columns
1. plus a space3 columns3 columns
10. plus a space4 columns4 columns

So the advice that a second level always needs four spaces is a habit, not a rule. Four spaces work under a dash, and they also work under 1. — you are then one column to the right of the content column, which is still inside the range that counts as a child list. What does not work is going too far. Four spaces past the content column turns the continuation into an indented code block:

- Level one

      this is code, not a list

The item text is followed by a <pre><code> block instead of a second paragraph, so the six spaces turned the content into code. Note the blank line. Indented code cannot interrupt a paragraph, so the code block only forms when the line is separated from the item text; without that blank line the same six spaces simply continue the paragraph.

When the indentation is too small

Indenting too little is the more common mistake, and its result is easy to miss. A line that is not indented far enough does not become a child of the item above it; it breaks out and becomes a separate list:

1. Parent
  - Child
<ol>
<li>Parent</li>
</ol>
<ul>
<li>Child</li>
</ul>

Two spaces were not enough under a 1. marker, whose text starts in the fourth column, so the bullet list escaped and became a sibling of the ordered one. Indent to three spaces and the bullet becomes a genuine child. The same rule explains the case where a child turns out to be a sibling: it was indented less than the content column of its parent, so the parser read it as a new block at the outer level.

Mixing ordered and unordered levels

Levels may change type freely. A bullet list may contain an ordered list, and an ordered list may contain a bullet list. The indentation rule does not change, because it is still measured from the parent marker:

- Prepare the release
  1. Tag the commit
  2. Publish the notes
- Announce the release

The result is one <ul> whose first item contains a nested <ol>, and the second item is a plain sibling of the first. The mixed form is the natural way to say “these are the phases” while listing “these are the steps” underneath one of them. It also has a cost: every change of level changes the width of the marker, so the indentation has to change with it, and a file that mixes the two is easy to break with a stray space.

When nesting gets too deep

Three levels is usually as deep as a list should go. A fourth level is possible, but the cost is real: the text of the deepest item starts nine columns in, the line wraps earlier, and the reader has to count the indents to work out which parent an item belongs to. Past three levels a list stops being a scannable structure and becomes a paragraph with punctuation, and the better move is to break the structure apart. A list of features with three sub-points each becomes a section per feature, with the sub-points as a short list inside it. You keep the same information, you give each level its own heading, and the heading carries the hierarchy that the whitespace was carrying before. A nested list is best when the second level is short; when the second level needs paragraphs of its own, it wants to be a section.

Common mistakes

Child indentActually renders asWhy
2 spaces under - a nested listthe content column is the third column
6 spaces under - an indented code blockfour spaces past the content column
2 spaces under 1. a separate sibling listthe content column is the fourth column
siblings indented 2 and 4one child list, but only by luckboth values are still inside the child range

Exercises

Rewrite the following plain text as Markdown. Use one unordered list for the two top-level items, put two children under the first item, put an ordered list of two steps under the second item, and indent every level to the column where the parent item’s text starts. Use spaces throughout, never tabs.

Set up the project
  Install pnpm
  Run pnpm install
Configure the build
  1. Set the target
  2. Build the output
Nested listsContent columnConsistent indentation

Approach:

The two top-level items are siblings, so they share one unordered list and one indent level. The children under the first item are two spaces in, because a dash marker occupies two columns. The ordered list under the second item is a child of that item, so it is indented to the same two-space column, and its own items are numbered with a period and a space.

Steps:

  1. Write the two top-level items as a hyphen, a space, and the text, all at the left margin.
  2. Indent the two children of the first item by two spaces and give each of them a hyphen and a space, so that they line up with the column where the parent’s text starts.
  3. Indent the ordered list under the second item by two spaces as well, and write its two items as 1. and 2. followed by a space.
  4. Check the result: rendering it must produce a two-item bullet list whose first item holds a nested bullet list and whose second item holds a nested ordered list numbered 1 and 2.

Answer:

- Set up the project
  - Install `pnpm`
  - Run `pnpm install`
- Configure the build
  1. Set the target
  2. Build the output

Summary

You can now create a nested list of any depth with indentation alone, and you know that the amount of indentation is measured from the width of the parent’s marker rather than from a fixed number of spaces. You know that two, three and four spaces can all be correct depending on the parent, that indenting too little turns a child into a sibling or a separate list, and that four spaces past the content column turns the content into a code block. You also know that ordered and unordered levels may be mixed freely, and that a list deeper than three levels is usually a sign that the content should become a section. The next page turns to the blockquote, the other block element in this chapter, where the rule that matters is not the marker but the range.

Found an issue with this content?

Tell us what could be improved.