Invalid list structure (list)

The list rule flags a <ul> or <ol> whose direct children are not all list items – a wrapper <div>, a heading, loose text or a sub-list placed next to the items. Screen readers then announce the wrong number of items or lose the list altogether. The fix is to make every direct child an <li> and move everything else inside or outside the list.

What the rule means

In HTML, a <ul> or <ol> may only contain <li> elements (plus <script> and <template>, which are never shown). The list tells assistive technology how many items there are and where each one starts; that only works when the structure is exactly list → item.

The rule checks every <ul> and <ol> without a role attribute. It fails when a direct child is:

  • another element that is not an <li> or an element with role="listitem",
  • visible text directly inside the list,
  • or when every <li> in the list has been given a different role.

Lists with their own role are skipped – for those, rules such as aria-required-children apply. Definition lists (<dl>) have separate rules. Elements hidden from assistive technology are ignored.

Who is affected

Blind and partially sighted people using a screen reader or a braille display. A screen reader announces "list, 5 items" on entry, lets people jump from item to item and says when the list ends. A wrapper <div> or a stray element breaks that: the count is wrong, or items are read as loose text without their place in the list.

Why the check fails

  • Slider and carousel libraries that insert a track <div> between the <ul> and its slides.
  • Component frameworks where a list item component renders its own wrapper <div> around the <li>.
  • Nested lists in the wrong place: the rich-text editor puts the sub-list next to the item instead of inside it.
  • Group labels inside the list: an <h3> or <p> used as a heading between items.
  • Separators as text: a | or · typed between the items of a footer list.
  • Menus where the <li> elements were all given role="none" but the <ul> kept its list role.

How to fix it

Make every direct child of the list an <li>. Wrappers go around the list or inside the item, sub-lists go inside the <li> they belong to, and separators come from CSS.

<!-- Before: a slider wraps the items in a div inside the ul -->
<ul class="product-slider">
  <div class="slider__track">
    <li class="product-card"><a href="/mugs/">Mugs</a></li>
    <li class="product-card"><a href="/plates/">Plates</a></li>
  </div>
</ul>
<!-- After: the wrapper sits outside, the li elements are direct children -->
<div class="slider__track">
  <ul class="product-slider">
    <li class="product-card"><a href="/mugs/">Mugs</a></li>
    <li class="product-card"><a href="/plates/">Plates</a></li>
  </ul>
</div>

The same for a nested list: it belongs inside its parent item.

<!-- Before: the sub-list sits next to "Shop", not inside it -->
<ul class="sitemap">
  <li><a href="/shop/">Shop</a></li>
  <ul><li><a href="/shop/mugs/">Mugs</a></li></ul>
</ul>
<!-- After: the sub-list is part of the "Shop" item -->
<ul class="sitemap">
  <li><a href="/shop/">Shop</a>
    <ul><li><a href="/shop/mugs/">Mugs</a></li></ul>
  </li>
</ul>

If a slider library cannot be configured, check whether it offers an option to use its own element as the list, or wrap the slides in plain <div>s and drop the list markup rather than keeping a broken one.

How to test it manually

  1. In the browser's developer tools, open the accessibility tree and select the list: every child should have the role "listitem".
  2. With a screen reader, move to the list (L in NVDA and JAWS). Is the number of items announced the number you see?
  3. Look at the visual page for things that look like lists – rows of links, steps, features with bullet icons – and check they are marked up as lists.
  4. The rule only checks lists that exist. Content that looks like a list but is built from <div>s or <br> line breaks passes and still hides its structure; that part of 1.3.1 needs a person.

1.3.1 Info and Relationships, Level A: structure that is visible has to be available in the markup. Related: 1.3.2 Meaningful Sequence, because the order of the items in the code is the order in which they are read.

How Reviseberg reports it

Reviseberg runs list on every crawled page. Each broken list is one occurrence, so a slider or menu in the site template appears on nearly every page. The issue list shows the rule with its severity, WCAG 1.3.1 at Level A, the number of elements and pages, and the points a fix gets you back. The detail view shows the selector and HTML snippet of each list and every affected page. You can mark a finding as "ignore", "can't fix" or "false positive" with a reason – "can't fix" fits a third-party widget you do not control; every decision is logged.

A clean result on this rule does not make 1.3.1 a pass on its own: whether content that looks like a list is marked up as one is a question for a person, and the criterion is only partly covered by automated checks.

  • undefined – the other half: an <li> that is not inside a list.
  • undefined – the same problem for ARIA roles such as role="list" or role="menu".
  • undefined – another part of the page's structure.

Check the list structure of your whole site – get a free scan

Frequently asked questions

May a <ul> contain a <div>?

Not as a direct child. Put the <div> inside the <li>, or around the whole list.

Where does a nested list go?

Inside the <li> it belongs to, after that item's text or link. A <ul> directly inside another <ul> fails the rule.

Is an empty <ul> a problem?

No. The rule passes an empty list, for example one that a script fills later.

Why is my navigation list not announced in Safari?

Safari with VoiceOver may drop list semantics when the list style is set to none. Some teams add role="list" for that; the list rule then skips the element, because it has a role of its own.

Sources

  1. W3C, Understanding SC 1.3.1 Info and Relationships – https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships
  2. Deque University, axe-core 4.13 rule list – https://dequeuniversity.com/rules/axe/4.13/list
  3. WHATWG, HTML Living Standard: the ul element – https://html.spec.whatwg.org/multipage/grouping-content.html#the-ul-element
  4. W3C, Technique H48: Using ol, ul and dl for lists or groups of links – https://www.w3.org/WAI/WCAG22/Techniques/html/H48

See what a scan finds on your site

One page in about thirty seconds, no email needed. The full report covers up to 100 pages and a keyboard journey.