Bullet lists

A bullet list is a list whose order does not matter, written as lines that start with a marker (-, * or +) followed by a space. It becomes a <ul> (unordered list) with one <li> per item, the HTML list elements.

Bring to the data center:

- laptop with console cable
- access badge
- the approved change number
<p>Bring to the data center:</p>
<ul>
<li>laptop with console cable</li>
<li>access badge</li>
<li>the approved change number</li>
</ul>

A bullet list may follow a paragraph directly, without a blank line in between, as long as the item has text. A blank line is still easier to read, and some older renderers need it.

- Laptop
* Badge
+ Phone

-Missing space
<ul>
<li>Laptop</li>
</ul>
<ul>
<li>Badge</li>
</ul>
<ul>
<li>Phone</li>
</ul>
<p>-Missing space</p>

The last line shows the other classic: without a space after the marker, the line is plain text.

Numbered lists

An ordered list is a list where the order matters, such as steps in a procedure. Each item starts with a number (up to nine digits) followed by a period or a closing parenthesis and a space. It becomes an <ol>, and the browser draws the numbers.

Because the browser does the numbering, the renderer only uses the first number, as the starting point. The numbers on the other lines are ignored:

1. Log in to the portal
1. Open **Meter readings**
1. Enter the reading and press **Submit**
<ol>
<li>Log in to the portal</li>
<li>Open <strong>Meter readings</strong></li>
<li>Enter the reading and press <strong>Submit</strong></li>
</ol>

This list uses 1. on every line. That is a popular style for long procedures: inserting a step does not mean renumbering everything, and the diff shows only the new line. A list can also start at another number, here 4; the browser then shows 4, 5, 6, whatever the source says on the later lines:

4. Restart the service
9. Check the dashboard
2. Close the change
<ol start="4">
<li>Restart the service</li>
<li>Check the dashboard</li>
<li>Close the change</li>
</ol>

If the numbers in the source matter to readers of the plain text, keep them correct; if not, 1. everywhere is easier to maintain. Do not put these two lists directly below each other with only a blank line in between: as explained under Ending a list, they would merge into one list numbered 1 to 6.

Numbers that are not lists

Two rules prevent ordinary sentences from turning into lists by accident, and they occasionally surprise people:

  • Inside a paragraph, only a list that starts with 1 can begin without a blank line. "The steps are:" followed directly by a line starting with 4. stays part of the paragraph.
  • A line that happens to start with a number and a period, such as a year, does become a list when it starts a paragraph. Escape the period with a backslash to prevent that.
The remaining steps are:
4. Restart the service
5. Check the dashboard

2026. A year of grid upgrades.

2026\. A year of grid upgrades.
<p>The remaining steps are:
4. Restart the service
5. Check the dashboard</p>
<ol start="2026">
<li>A year of grid upgrades.</li>
</ol>
<p>2026. A year of grid upgrades.</p>

For the first case, put a blank line before the list. More on the backslash is on Blockquotes, Horizontal Rules and Escaping.

Nested lists

A nested list is a list inside a list item, used for sub-steps or sub-points. To nest a list, indent its lines so that the marker lines up with the start of the text of the parent item, not with the parent's marker:

  • under - Network, the text starts in column 3, so indent 2 spaces;
  • under 1. Prepare, the text starts in column 4, so indent 3 spaces;
  • under 10. Verify, indent 4 spaces.
- Network
  - core switches
  - firewalls
- Servers
  - portal
    - web tier
    - database

1. Prepare
   - take a backup
   - announce the window
2. Run the upgrade
<ul>
<li>Network
<ul>
<li>core switches</li>
<li>firewalls</li>
</ul>
</li>
<li>Servers
<ul>
<li>portal
<ul>
<li>web tier</li>
<li>database</li>
</ul>
</li>
</ul>
</li>
</ul>
<ol>
<li>Prepare
<ul>
<li>take a backup</li>
<li>announce the window</li>
</ul>
</li>
<li>Run the upgrade</li>
</ol>

Indenting further is allowed, up to a point: four spaces under a bullet item also nests. Indenting less than the parent's text breaks the nesting, and this is the mistake behind most "my numbered list restarts at 1" questions:

1. Prepare
  - take a backup
  - announce the window
2. Run the upgrade
<ol>
<li>Prepare</li>
</ol>
<ul>
<li>take a backup</li>
<li>announce the window</li>
</ul>
<ol start="2">
<li>Run the upgrade</li>
</ol>

With only two spaces under 1. , the sub-items are not inside step 1. They form a separate bullet list, which ends the numbered list; step 2 then starts a new numbered list (start="2"). In this renderer the numbers still look right, but the structure is wrong, and in renderers that ignore the start number the second list begins at 1 again.

Tight and loose lists

Blank lines inside a list change how it is rendered. A tight list has no blank lines between its items; the item text goes straight into the <li>. A loose list has a blank line between at least two items, or an item that contains two blocks separated by a blank line; then the text of every item is wrapped in a <p>, which usually adds space between the items.

- Check the backup
- Stop the service
- Apply the patch

---

- Check the backup

- Stop the service
- Apply the patch
<ul>
<li>Check the backup</li>
<li>Stop the service</li>
<li>Apply the patch</li>
</ul>
<hr>
<ul>
<li>
<p>Check the backup</p>
</li>
<li>
<p>Stop the service</p>
</li>
<li>
<p>Apply the patch</p>
</li>
</ul>

One stray blank line anywhere in the second list is enough to make all its items loose. Use tight lists for short items and loose lists when items are paragraphs of their own; and if a list suddenly has gaps between its items, look for a blank line.

Paragraphs and code inside items

A list item can hold more than one line of text. Any block indented to the item's text column (the same rule as for nesting) belongs to the item: a second paragraph, a code block, a quote. This is how a runbook step carries its command:

1. Make a backup of the portal database:

   ```
   pg_dump portal > portal-2026-10-02.sql
   ```

2. Check that the file is not empty.

   An empty file means the backup failed. Stop and call the DBA.
<ol>
<li>
<p>Make a backup of the portal database:</p>
<pre><code>pg_dump portal &gt; portal-2026-10-02.sql
</code></pre>
</li>
<li>
<p>Check that the file is not empty.</p>
<p>An empty file means the backup failed. Stop and call the DBA.</p>
</li>
</ol>

The code block and the second paragraph are indented three spaces, to line up with the text after 1. , so they stay inside their steps, and the numbering continues. Because the items contain blank lines, this list is loose. Forget the indentation and the code block ends the list:

1. Make a backup of the portal database:
```
pg_dump portal > portal-2026-10-02.sql
```
2. Check that the file is not empty.
<ol>
<li>Make a backup of the portal database:</li>
</ol>
<pre><code>pg_dump portal &gt; portal-2026-10-02.sql
</code></pre>
<ol start="2">
<li>Check that the file is not empty.</li>
</ol>

Fenced code blocks are explained on Code: Inline Code and Fenced Code Blocks.

Ending a list

A list ends at the first line that is not indented and not a new item, after a blank line. Two lists that follow each other with only a blank line in between merge into one (loose) list. To keep them apart, put something in between: a paragraph or a heading, which usually makes the document clearer anyway.

- Tomasz Nowak
- Emeka Obi

Service desk:

- Mei Chen
- Amara Okafor
<ul>
<li>Tomasz Nowak</li>
<li>Emeka Obi</li>
</ul>
<p>Service desk:</p>
<ul>
<li>Mei Chen</li>
<li>Amara Okafor</li>
</ul>

Where raw HTML is allowed, an HTML comment (<!-- -->) on its own line also separates two lists without showing anything.

Task lists

A task list item is a list item that starts with [ ] (open) or [x] (done) after the marker, which GitHub and other platforms render as a checkbox. Task lists are an extension defined in GitHub Flavored Markdown, not part of CommonMark, and the renderer on this site does not include them, so this example is shown as source and an illustration:

## Change CHG-2291: core switch firmware

- [x] Change approved
- [x] Backup of running configuration
- [ ] Maintenance window announced
- [ ] Rollback plan tested
Change CHG-2291: core switch firmware

☑ Change approved
☑ Backup of running configuration
☐ Maintenance window announced
☐ Rollback plan tested

The GFM specification turns each item into an <li> that starts with a disabled checkbox, roughly <li><input type="checkbox" disabled> Change approved</li>. A renderer without the extension keeps the brackets as text:

- [x] Change approved
- [ ] Maintenance window announced
<ul>
<li>[x] Change approved</li>
<li>[ ] Maintenance window announced</li>
</ul>

Some details worth knowing:

  • The brackets need exactly one character between them: a space for open, x or X for done. And there must be a space after the closing bracket.
  • In GitHub issues, pull requests and comments the checkboxes are interactive: people who can edit the issue or comment can tick them in the browser, and GitHub updates the Markdown for them. For a task list in an issue description, the progress also appears in the repository's list of issues.
  • In a .md file in a repository the checkboxes are shown but not clickable; you change them by editing the file.
  • Many other tools understand the same syntax, among them GitLab, Obsidian and Slack's Markdown block for apps. Jira's editor turns [] into an action item as you type. For markdown-it a plugin is needed.

More GitHub-specific features, such as mentions, issue references and alerts, are on Markdown on GitHub and GitLab.

Writing good lists

  • Numbers for order, bullets for everything else. If the steps must happen in sequence, use a numbered list; a reader can then say "I'm stuck at step 4".
  • One action per step. "Stop the service and apply the patch and restart" hides two places where things can go wrong.
  • Parallel wording. Start every item the same way, for example with a verb: "Check…", "Stop…", "Apply…".
  • Keep nesting shallow. Two levels are usually enough; deeper structure is often better as a heading with its own list.
  • Consider a table when every item has the same few properties, such as name, role and phone number; see Tables.

How to structure runbooks and procedures as a whole is covered in Writing Tickets and Technical Documentation.