All rules

Sheath rule

best-practices-require-li-container

List items (<li>) must be inside <ul>, <ol>, or <menu> elements.
Package
Core
Default severity
error by default
Auto-fix
Manual fix

#Why

The HTML specification requires <li> elements to be direct children of list containers. Placing them elsewhere:

  • Creates invalid HTML
  • Breaks screen reader list announcements
  • Can cause unpredictable styling

#Examples

#Bad

<!-- li outside of list -->
<div>
<li>Item 1</li>
<li>Item 2</li>
</div>
<!-- li inside wrong parent -->
<section>
<li>Standalone item</li>
</section>
<!-- li wrapped in div inside list -->
<ul>
<div>
<li>Item 1</li>
</div>
</ul>

#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>

#Valid Parents for <li>

  • <ul> - Unordered list
  • <ol> - Ordered list
  • <menu> - Menu of commands

#List-item Components

A template whose <li> has no surrounding element is treated as a reusable fragment and is not reported because its list 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. <div><li>...</li></div> is still a finding in components and pages alike.

#Notes

  • <li> must be a direct child of the list container
  • Don't wrap <li> elements in <div> - use CSS for styling
  • For <dt> and <dd> relationships, see a11y-list-semantics

#References

#Related Rules