All rules

Sheath rule

a11y-list-semantics

List items must be inside proper list containers.
Package
Core
Default severity
error by default
Auto-fix
Manual fix

#Why

<li> elements must be direct children of <ul>, <ol>, or <menu> elements for proper semantics and accessibility. Similarly, <dt> and <dd> elements must be inside <dl> elements. Screen readers use this structure to announce lists properly.

#Examples

#Bad

<!-- li outside of list container -->
<div>
<li>Item 1</li>
<li>Item 2</li>
</div>
<!-- li nested in wrong element -->
<ul>
<div>
<li>Item 1</li>
</div>
</ul>
<!-- dt/dd outside of dl -->
<div>
<dt>Term</dt>
<dd>Definition</dd>
</div>

#Good

<!-- Unordered list -->
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
<!-- Ordered list -->
<ol>
<li>First step</li>
<li>Second step</li>
</ol>
<!-- Menu list -->
<menu>
<li><button>Action 1</button></li>
<li><button>Action 2</button></li>
</menu>
<!-- Definition list -->
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language</dd>
</dl>
<!-- Definition list with div grouping (HTML5 valid) -->
<dl>
<div>
<dt>CSS</dt>
<dd>Cascading Style Sheets</dd>
</div>
</dl>

#List-item Components

A template whose <li>, <dt>, or <dd> has no surrounding element is treated as a reusable fragment and is not reported because its container may be provided by the calling template.

{{-- Not reported: resources/views/components/nav-link.blade.php --}}
@props(['href'])
<li><a href="{{ $href }}">{{ $slot }}</a></li>

Once the template supplies a surrounding element, that relationship is checked in components and pages alike.

#Notes

  • <li> must be a direct child of <ul>, <ol>, or <menu>
  • <dt> and <dd> must be direct children of <dl> (or inside a <div> within <dl>)
  • HTML5 allows <div> elements inside <dl> to group <dt>/<dd> pairs
  • Don't wrap <li> elements in <div> - use CSS for styling instead

#References

#Related Rules