Who it affects
Someone who is blind, checking which postcodes an online florist delivers to hears 'list, 2 items' when there are six areas on screen, because the others are wrapped in divs.
Someone who uses a screen reader shortcut to skip past a list lands at the end and misses the items the browser did not count.
Someone using a reader mode or a simplified view sees the areas collapse into a run of words with no bullets.
Broken versus fixed
Both examples are live and rendered in a sandboxed frame. The broken one is deliberately broken.
Some screen readers announce: list, 2 items. There are six areas on screen; four of them sit inside divs.
Announced: list, 6 items. Each area is one item and the person can step through them.
Show the markup behind both examples
<style>body{font-family:system-ui;margin:0;padding:16px}ul{margin:4px 0 0;padding-left:22px}.area{margin:2px 0}</style>
<p style="margin:0"><strong>Same-day delivery areas</strong></p>
<ul>
<li>NR1 City centre</li>
<div class="area"><li>NR2 Golden Triangle</li></div>
<div class="area"><li>NR3 New Catton</li></div>
<div class="area"><li>NR4 Eaton</li></div>
<div class="area"><li>NR5 Costessey</li></div>
<li>NR6 Hellesdon</li>
</ul>
<style>body{font-family:system-ui;margin:0;padding:16px}ul{margin:4px 0 0;padding-left:22px}.area{margin:2px 0}</style>
<p style="margin:0"><strong>Same-day delivery areas</strong></p>
<ul>
<li class="area">NR1 City centre</li>
<li class="area">NR2 Golden Triangle</li>
<li class="area">NR3 New Catton</li>
<li class="area">NR4 Eaton</li>
<li class="area">NR5 Costessey</li>
<li class="area">NR6 Hellesdon</li>
</ul>
Test it by hand in two minutes
- Right click the list, choose Inspect, and expand the ul or ol. Every direct child should be an li (script and template are also allowed).
- With NVDA or VoiceOver, move to the list. The announced item count should match what you can see.
- Turn CSS off (in Chrome DevTools open the Rendering drawer and emulate a print or no-CSS view, or use the Web Developer extension). Each item should still show as a bullet or number on its own line.
The fix
<ul class="areas">
<div class="area"><li>NR1 City centre</li></div>
<div class="area"><li>NR2 Golden Triangle</li></div>
</ul>
<ul class="areas">
<li class="area">NR1 City centre</li>
<li class="area">NR2 Golden Triangle</li>
</ul>
Move the class to the li and drop the wrapper. If your component framework insists on a wrapper, render it inside the li, not around it.
Note placed inside the list
<ul>
<li>Monday</li>
<li>Tuesday</li>
<p>Order by 2pm for same-day delivery.</p>
</ul>
<ul>
<li>Monday</li>
<li>Tuesday</li>
</ul>
<p>Order by 2pm for same-day delivery.</p>
The note belongs after the list, not in it.
Heading inside the list
<ul>
<h3>North Norwich</h3>
<li>NR3 New Catton</li>
</ul>
<h3>North Norwich</h3>
<ul>
<li>NR3 New Catton</li>
</ul>
Headings go before the list they introduce.
Nested list outside its item
<ul>
<li>Zone 1</li>
<ul><li>NR1</li></ul>
</ul>
<ul>
<li>Zone 1
<ul><li>NR1</li></ul>
</li>
</ul>
A sub-list lives inside the li it belongs to, so screen readers announce it as nested.
Common mistakes
- Wrapping each li in a div so the framework can attach a key or a class.
- Putting the heading or intro paragraph inside the ul to keep it in the same box.
- Nesting a ul directly inside the parent ul instead of inside an li.
- Replacing the list with divs and typed bullet characters, which loses the list entirely.
WCAG criteria this rule maps to
axe-core tags this rule as WCAG 2.2 level A. It is one of the checks for:
- 1.3.1 Info and Relationships (level A). Official W3C text.
The scanner can see any direct child of a ul or ol that is not li, script or template. It cannot tell whether a group of items that are not in a list at all should have been one. Automated tools find only part of the accessibility problems on a page; a pass on this rule is not a pass on the criterion.
Related rules
listitem
An li is only a list item when its parent is a ul, ol or menu.
A
Definition lists must be built from matching terms and descriptions
definition-list
A dl is a list of terms and their descriptions: each dt (the term) is followed by one or more dd (the description).
A
Terms and descriptions must sit inside a definition list
dlitem
dt and dd only mean term and description when they are inside a dl.