List Items Must Be Contained in UL or OL: How to Fix It

No Comments
List items must be contained in ul or ol: how to fix it

What this check flags

This check fails when an <li> element sits outside a proper list container — not directly inside a <ul>, <ol>, or <menu> parent. That breaks the HTML contract for lists: a list item only means "item in a list" when it lives inside one. Orphaned <li> elements are invalid markup, and screen readers lose the "list of 5 items" context that helps users navigate and understand grouped content.

The practical damage is that assistive tech can no longer announce list size or position ("item 2 of 5"), and users lose the ability to jump list-to-list. It is a small structural slip with an outsized effect on how navigable your grouped content is.

A real failing example, and the fix

The most common cause is a wrapper element wedged between the list and its items — a <div> added for styling that severs the required parent-child relationship:

<!-- Broken: a div sits between <ul> and its <li>s -->
<ul class="features">
  <div class="row">
    <li>Automated crawling</li>
    <li>Scheduled reports</li>
    <li>Issue prioritization</li>
  </div>
</ul>

Here the <li> elements are children of a <div>, not the <ul>, so they are orphaned. The <li> must be a direct child of the list. Remove the intermediate wrapper; if you need a flex or grid row, style the <ul> itself:

<ul class="features row">   <!-- style the list directly -->
  <li>Automated crawling</li>
  <li>Scheduled reports</li>
  <li>Issue prioritization</li>
</ul>

<style>
  .features.row { display: flex; gap: 1rem; list-style: none; }
</style>

The other frequent offender is a lone <li> pasted into flowing content with no list around it at all — often a copy-paste leftover. If it is genuinely a single item, it probably should not be an <li>; if it belongs to a list, wrap it (and its siblings) in a <ul> or <ol>.

What is (and is not) valid list structure

The rule is stricter than "an li somewhere near a ul." This table lays out what passes:

StructureValid?Note
<ul><li>YesUnordered list, item is a direct child
<ol><li>YesOrdered list, item is a direct child
<menu><li>YesAlso a valid list parent for li
<ul><div><li>NoWrapper breaks the direct relationship
<li> with no list parentNoOrphaned item, invalid
<ul><li> → nested <ul>YesNested lists go inside an li, not between
<ul><script>/<template>YesThese are the only other permitted ul children

Nesting is the subtlety worth calling out: a sub-list belongs inside a parent <li>, not floating between the parent list and its items. Getting that wrong is another way to orphan an <li>.

How to detect it

  1. Run an HTML validator (the W3C Nu checker or an automated a11y tool). Orphaned <li> and illegal <ul>/<ol> children are reported as parent/child errors.
  2. Run axe or Lighthouse; the "list items must be contained in ul/ol" and "lists contain only li" rules catch both directions of the problem.
  3. Search your templates for a <div> or other element sitting directly inside a <ul>/<ol> — the classic styling-wrapper culprit.
  4. Inspect the rendered DOM, since JavaScript components (especially framework loops) sometimes inject wrapper nodes that split the list from its items.
  5. Grep for stray <li> tags in content that was pasted or migrated, where the surrounding <ul> may have been dropped.

How to fix it

  1. Make every <li> a direct child of a <ul>, <ol>, or <menu> — delete any wrapper element between them.
  2. Need a flex/grid layout? Apply display to the list element itself instead of introducing an inner container.
  3. For nested lists, place the child <ul>/<ol> inside a parent <li>, never directly under the outer list.
  4. Wrap any orphaned <li> in a real list container, or convert it to the correct element (a paragraph, for instance) if it was never a list item to begin with.
  5. Re-validate the page to confirm no orphaned items or illegal list children remain.

FAQ

Can I put a div inside a ul to group items?

No. The only elements HTML permits as direct children of <ul> and <ol> are <li>, plus <script> and <template>. A grouping <div> orphans the items it contains. If you need layout, style the list or the items directly with flexbox or grid.

How do I do a multi-column or flex list layout then?

Apply display: flex or display: grid to the <ul> itself and let the <li> children flow into columns. You almost never need an intermediate wrapper to lay a list out — CSS on the list handles it while keeping the markup valid.

Where do nested lists go?

Inside a parent <li>. A sub-list is content belonging to a list item, so the nested <ul> or <ol> goes within that <li> — not between the outer list and its items, which would orphan them.

What if I only have one item — can it be a bare li?

A single item still needs a list parent if you want list semantics; a one-item <ul> is valid. But if it is truly a standalone line of content, it probably should not be an <li> at all — use a paragraph or the appropriate element instead.

Does this affect SEO?

Indirectly. Broken list structure is invalid HTML, and clean, semantic markup helps crawlers parse and understand grouped content — the same well-formed structure that helps screen readers. It sits alongside other structural checks like not faking headings with bold text. For the wider picture, see accessibility and SEO.

Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.

About SEO ProCheck

Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.

Work With Me

Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.

Subscribe to our newsletter!

More from our blog