How to fix a list with the wrong children, or a list item outside a list?
list page
The issue
When a list is marked up properly, a screen reader says “list, five items” before reading it, and lets the listener move from item to item or skip the list. When the markup is broken, the count is wrong, items are read as loose text, or the list isn’t announced as one. Navigation menus, feature lists and step-by-step instructions all lose the structure that made them easy to follow.
The cause is one of two structural mistakes. Either a <ul> or <ol> has something other than <li> directly inside it, such as a <div> wrapper or a heading, or an <li> sits somewhere other than inside a list. WCAG 1.3.1 requires structure conveyed visually to be available in the markup too.
Scope
Two rules check lists:
listchecks each visible<ul>and<ol>. Only<li>,<script>and<template>may be direct children; anything else is reported, naming the elements found. A list given a role other thanlistis skipped.listitemchecks each visible<li>. Its direct parent must be a<ul>,<ol>or<menu>, or carryrole="list".
Elements hidden with hidden, aria-hidden="true", or an inline display: none or visibility: hidden, on the element or an ancestor, are skipped.
How to check you have it
- In probeo: the page reports
list, “<ul> and <ol> must only directly contain <li>, <script> or <template> elements”, orlistitem, “<li> elements must be contained in a <ul> or <ol>”. Both have serious impact and map to WCAG 1.3.1. - By hand: in the browser’s DevTools, inspect the list and look at its direct children. Every one should be an
<li>, and every<li>should sit directly inside a list. - With a tool: axe DevTools reports both rules by the same names, and Lighthouse’s accessibility audit includes them.
The fix
Make every direct child of a list an <li>, and put every <li> directly inside a list.
Move wrappers inside the item rather than around it. If a component library wraps each item in a <div>, change it to render the <li> as the outer element.
<!-- Before: a div between the list and its items -->
<ul>
<div class="item"><li>Free shipping</li></div>
</ul>
<!-- After -->
<ul>
<li class="item">Free shipping</li>
</ul>Done when: no list has a non-item child and no item sits outside a list, and the check above comes back clean.
Do not
- Do not put headings or paragraphs directly inside a
<ul>; put them inside an<li>or before the list. - Do not use
<li>for things that aren’t list items just to get its styling. - Do not fix it by adding
role="none"to the list, which removes the structure instead of repairing it.
FAQ
Why does a wrapper div matter if the page looks right?
Screen readers don’t see the layout; they see the structure. A <div> between a list and its items breaks the parent-child relationship the list depends on, so the items may stop being counted as part of it.
Is a navigation menu a list?
Usually, yes: a <nav> holding a <ul> of links is the common pattern, and screen readers announce how many links it has. The same structural rules apply.
What about a list built from divs with ARIA roles?
role="list" and role="listitem" can describe a list built from other elements. A native <ul> or <ol> is simpler and needs no extra attributes to work.
Which product detects this
Probeo checks this on every page of your site as part of Site Clarity. This page explains one instance; the product tells you every page that has it.