Lists
A list tells a screen reader user how many things are coming before they hear them. That small fact saves time on every page. You get it for free with the right HTML tags. Fake lists throw it away.
In one minute
- A real list is announced with its size, like "list, 4 items". Each item can say "1 of 4".
<ul>: order does not matter.<ol>: order matters.<dl>: names with values.- Lines split with
<br>, stacked<div>s, or typed "•" characters are not lists. - In Safari,
list-style: nonecan remove the list meaning. Addrole="list"to put it back.
Imagine a waiter who says "We have four specials today" before naming them. You know when he will finish. A real list is that waiter. A fake list is a waiter who names dishes until he stops, and you never know if more are coming. A screen reader is software that reads the page out loud. It reads what the HTML says, not what the page looks like.
1. It looks like a list. Is it one?
Below is the basket in a food-delivery app. All four versions look much the same. Only one is a list to a screen reader.
Step 1. Pick how the basket is built. Step 2. Press "Read next" to move through it like a screen reader.
Your basket
Real lists also help people move fast. In NVDA and JAWS, pressing L jumps to the next list. In VoiceOver, the rotor (a quick menu of page parts) can do the same. A fake list cannot be found that way.
In the lab, pick "Typed • characters" and press "Read next". What does the screen reader say before each dish?
2. Three kinds of list: ul, ol and dl
HTML has three list types. Choose by asking one question: what links the items together?
| Tag | Use it when | Example |
|---|---|---|
<ul> unordered list | The order does not change the meaning. | Toppings on a pizza. |
<ol> ordered list | Swapping two items would change the meaning. | Steps in a recipe. A top-10 chart. |
<dl> description list | Each item is a name with a value. | Subtotal: ₹420. Delivery: ₹30. |
In a <dl>, each name goes in a <dt> (description term). Its value goes in a <dd> (description details).
Order summary as a dl
Good- Subtotal
- ₹420
- Delivery
- ₹30
- Total
- ₹450
<dl> <dt>Subtotal</dt> <dd>₹420</dd> <dt>Delivery</dt> <dd>₹30</dd> <dt>Total</dt> <dd>₹450</dd> </dl>
Screen readers announce description lists in different ways. Some say "description list" or "list, 3 items". Some say less. The pairing is still kept in the code, which helps.
Step 1. Choose a list type for each piece of content. Step 2. Press "Check my answers".
A playlist where songs play in the order shown. Which tag? (Answer: <ol>, because the order matters.)
3. Navigation menus as lists
Most sites put menu links inside a <ul>. It is common and helpful: the user hears "list, 5 items" and knows the menu's size.
It is not required. A <nav> with plain links is still accessible.
<nav aria-label="School portal">
<ul>
<li><a href="/timetable">Timetable</a></li>
<li><a href="/homework">Homework</a></li>
<li><a href="/results">Results</a></li>
</ul>
</nav>
The exact words differ between screen readers. The size of the menu is the useful part.
Open this page's source code (Ctrl/Cmd + U). Is the header menu at the top a list? Would a list help with only two links?
4. Style it without breaking it
Designers often remove the bullets with list-style: none. In Safari, this can make VoiceOver stop treating it as a list.
This is a known WebKit choice (WebKit is the engine inside Safari). The reasoning: if it does not look like a list, maybe it is not one.
The fix is to say it plainly in the HTML: add role="list" to the <ul> or <ol>.
A role tells assistive technology what kind of thing an element is. Here, it repeats what the tag already means, so Safari keeps it.
Step 1. Choose the styling. Step 2. Choose the browser. Compare what is announced.
Browse genres
Newer Safari versions usually keep list meaning for lists inside a <nav>. Adding role="list" anyway is a safe habit.
Some code checkers warn that the role is "redundant". Here it is on purpose, so leave it.
You removed the bullets from a list of bookshop genres. Which one attribute do you add, and to which tag?
5. Nested lists, and lists that are not lists
A list can hold another list. The inner list must sit inside an <li>, never straight inside the outer <ul>.
Screen readers then announce the inner list and often its nesting level.
Step 1. Switch between the right and the wrong way to nest a bookshop menu.
Do not use a list only to place things on screen. One lonely item, or a paragraph split into "items" to get spacing, is noise. Ask: is this a group of similar things a user may want to count or skip? If yes, use a list. If no, use CSS for the layout.
A grid of 12 book cards in a search result. List or not? (Yes: they are similar items, and "list, 12 items" tells the user how many results there are.)
Common mistakes
| You see | Why it is a problem | Fix |
|---|---|---|
Lines split with <br> and "•" | No count, no list jumping. "Bullet" is read as text. | <ul> with <li> |
Steps in a <ul> | The order is lost in the code. | <ol> |
| Key–value pairs as loose text | Names and values are not tied together. | <dl> with <dt>/<dd> |
list-style: none and nothing else | Safari with VoiceOver may drop the list. | Add role="list". |
<ul> directly inside <ul> | Invalid HTML. Counts can come out wrong. | Put the inner list inside an <li>. |
| A list used just for spacing | Announces a structure that is not there. | Use CSS for layout. |
Remember
- Real lists announce their size. Fake lists do not.
ulfor any order,olwhen order matters,dlfor name–value pairs.- Never build a list from
<br>, divs or typed bullets. - Removed the bullets? Add
role="list"for Safari. - Nest a list inside an
<li>. Do not use lists just for layout.