Lists group related items. HTML has three kinds, and the right one tells readers and assistive technology how the items relate. Screen readers announce a list and how many items it has, which helps people decide whether to listen or skip ahead.
Unordered lists: ul
Use ul when the order of the items does not change their meaning:
<h2>Allergens</h2>
<ul>
<li>Gluten</li>
<li>Milk</li>
<li>Eggs</li>
</ul>
Each item is an li (list item). Browsers show bullets by default.
Ordered lists: ol
Use ol when the order matters, such as steps, rankings or instructions:
<h2>Method</h2>
<ol>
<li>Mix the flour, water and salt.</li>
<li>Rest the dough for 30 minutes.</li>
<li>Knead for 10 minutes.</li>
</ol>
Browsers number the items for you. Never type the numbers into the text; they would duplicate the automatic numbering and go wrong as soon as someone adds a step.
A quick test: if you shuffled the items, would the meaning change? If yes, use ol. If no, use ul.
Controlling the numbers
ol has three attributes that change the numbering:
| Attribute | Effect | Example |
|---|---|---|
start | Number of the first item | <ol start="4"> starts at 4 |
reversed | Counts down instead of up | <ol reversed> |
type | Numbering style: 1, a, A, i or I | <ol type="a"> |
An individual li can also take a value to set its number, and the items after it continue from there.
<h2>Top three loaves this week</h2>
<ol reversed>
<li>Seeded rye</li>
<li>Wholemeal tin</li>
<li>Classic sourdough</li>
</ol>
<p>Steps 4 to 6 continue after the photo.</p>
<ol start="4">
<li>Shape the loaf.</li>
<li>Prove overnight in the fridge.</li>
<li>Bake at 230°C for 40 minutes.</li>
</ol>
The first list shows 3, 2, 1. The second continues from 4.
Use the type attribute when the numbering style is part of the meaning, for example legal clauses referred to as "clause b". For purely visual changes, use CSS list-style-type instead.
Nesting lists
A nested list goes inside an li, after that item's text. It is never a direct child of ul or ol.
<!-- Wrong: ul directly inside ul -->
<ul>
<li>Breads</li>
<ul>
<li>Sourdough</li>
</ul>
</ul>
<!-- Right: the nested list belongs to its parent item -->
<ul>
<li>Breads
<ul>
<li>Sourdough</li>
<li>Rye</li>
</ul>
</li>
<li>Pastries
<ul>
<li>Croissant</li>
<li>Pain au chocolat</li>
</ul>
</li>
</ul>
The correct version tells assistive technology that "Sourdough" and "Rye" are kinds of bread. The wrong version breaks that relationship and is invalid HTML.
You can mix list types. A numbered recipe step can contain a bulleted list of ingredients for that step. Keep nesting shallow, though: more than two or three levels is hard to follow for everyone.
Description lists: dl
A dl holds groups of terms (dt) and descriptions (dd). Use it for name and value pairs: glossaries, metadata, product specifications and frequently asked questions.
<h2>Loaf details</h2>
<dl>
<dt>Weight</dt>
<dd>800g</dd>
<dt>Flour</dt>
<dd>Organic stoneground wholemeal</dd>
<dt>Allergens</dt>
<dd>Gluten</dd>
<dd>Sesame</dd>
</dl>
A term can have several descriptions, as "Allergens" does, and several terms can share one description, for example two spellings of the same word.
To style each pair as a group, you may wrap each set of dt and dd elements in a div. This is valid only directly inside a dl:
<dl>
<div>
<dt>Weight</dt>
<dd>800g</dd>
</div>
<div>
<dt>Price</dt>
<dd>£4.50</dd>
</div>
</dl>
Lists in navigation
Site navigation is usually a list of links, because it is a set of related items. Wrapping it in a list lets screen reader users hear how many links there are:
<nav aria-label="Main">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/menu">Menu</a></li>
<li><a href="/classes">Classes</a></li>
</ul>
</nav>
The nav element and the aria-label are explained in lesson 11.
Styling lists without losing meaning
Designers often want lists without bullets, such as a horizontal menu. Remove the markers with CSS (list-style: none) rather than replacing the list with div elements.
Safari with VoiceOver may stop announcing a list when its markers are removed with list-style: none. For lists where the count really helps, such as navigation, you can keep the semantics by adding role="list" to the ul. The Web Accessibility Essentials course explains when ARIA roles like this are appropriate.
Common mistakes
| Mistake | Fix |
|---|---|
| Typing "1." or "•" in the text | Use ol or ul and let the browser add markers |
Nested ul directly inside ul | Put the nested list inside an li |
| Using a list just to indent text | Use CSS margin or padding |
Paragraphs separated by br for a list of points | Use a real list |
Summary
- Use
ulwhen order does not matter andolwhen it does. - Control numbering with
start,reversed,typeandli value. - Put nested lists inside an
li, never directly insideulorol. - Use
dlwithdtandddfor terms and descriptions or name and value pairs. - Change how lists look with CSS, and keep the list markup for its meaning.