Lists

Choose the right list for the content and nest one correctly.

05of 22
≈ 9Min read
6Parts

Three lists, three meanings

A list is announced with its length — "list, five items" — and a screen reader user can jump from item to item. That is the practical reason to use a real list instead of paragraphs beginning with a dash.

  • <ul> — the order does not matter. Ingredients, features, links.
  • <ol> — the order is the content. Steps, rankings, legal clauses.
  • <dl> — name and value pairs. A glossary, a specification sheet, metadata.

Only li inside a list

A <ul> or <ol> may contain only <li> children (plus script and template). Everything else goes inside an <li>. A nested list belongs inside the <li> it hangs from, not between two of them.

a nested list
<ul>
  <li>Front end
    <ul>
      <li>HTML</li>
      <li>CSS</li>
    </ul>
  </li>
  <li>Back end</li>
</ul>
The classic mistake

Closing the <li> before the nested <ul> puts the sub-list outside any item. It usually still looks right, and the structure a screen reader reads is wrong.

Numbering you control

<ol> takes start to begin somewhere other than 1, reversed to count down, and type for letters or roman numerals. A single <li> can override with value.

continuing a list after an aside
<ol start="4">
  <li>Proof for an hour</li>
  <li>Shape and rest</li>
</ol>

<ol type="a">
  <li>Painted</li>
  <li>Veneered</li>
</ol>

type changes the marker but the list is still numbered for assistive technology. To change only the look, use CSS list-style-type instead.

Description lists

One <dt> may have several <dd> values, and several <dt> may share one <dd>. HTML5 allows wrapping each pair in a <div>, which is what makes a <dl> easy to lay out with grid.

a specification
<dl>
  <div>
    <dt>Material</dt>
    <dd>Aluminium frame, MDF leaf</dd>
  </div>
  <div>
    <dt>Tolerance</dt>
    <dd>1 mm</dd>
  </div>
</dl>

Styling without breaking meaning

A navigation menu is a list of links — keep the <ul> and remove the bullets in CSS. list-style: none on some browsers strips the list semantics from VoiceOver; adding role="list" back puts them in place.

a clean menu
nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  gap: 1.5rem;
}

Markers

styling the number itself
li::marker {
  color: #8a8f98;
  font-variant-numeric: tabular-nums;
}

ol {
  padding-left: 1.4em;   /* room for the markers */
}

Practice