Sheath rule
best-practices-require-li-container
List items (
<li>) must be inside <ul>, <ol>, or <menu> elements.
- Package
- Core
- Category
- Best Practices
- 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
- HTML Spec: li Element - The li element content model
- MDN: li Element - Documentation on list items
#Related Rules
- a11y-list-semantics - Full list semantics checking