ADA Compliance Professionals

    List items must be inside ul or ol

    Last updated:

    Who it helps:
    Blind
    Standard:
    WCAG 2.2 Level A

    List items (li) must not appear without ul or ol parents

    Every li element must be a child of a ul or ol.

    This issue appears when bullets are faked with CSS or when HTML is pasted without proper containers. It affects screen reader users who rely on list roles and counts to understand structure.

    Why It Matters

    Screen readers announce "list" and the number of items, then let users jump item by item. Orphan li elements remove that structure, so users hear a stream of text with no context.

    People with low vision or cognitive disabilities benefit from consistent list semantics for orientation. Braille displays and accessibility trees also depend on proper list markup. This aligns with WCAG 2.2 Success Criterion 1.3.1 (Info and Relationships).

    Common Causes

    • Using li elements without wrapping ul or ol containers.
    • Styling paragraphs or divs to look like bullets instead of using real lists.
    • CMS/WYSIWYG editors stripping ul/ol during paste or when switching modes.
    • Copy/paste from documents that inserts plain text dashes or numbers.
    • Incorrect nesting (placing a nested ul/ol as a sibling of li instead of inside it).
    • Misusing ARIA roles (role="list"/"listitem") instead of native list elements.

    How to Fix

    • Wrap every li in the correct parent: use ul for unordered content, ol for ordered steps.
    • Keep nesting valid: a nested list must be inside the li it belongs to (li > ul/ol > li ...), not as a sibling.
    • Replace visual bullets made with CSS or characters (•, -, —) with semantic ul/li markup.
    • Do not rely on ARIA to replace native lists. Prefer ul/ol/li; only use ARIA if you cannot use native elements.
    • Clean CMS content: use the editor’s list tools, and configure paste rules to preserve ul/ol.
    • If the list order matters (instructions, rankings), switch to ol and ensure items represent the correct sequence.

    How to Test

    • Visual/DOM check: Inspect the HTML and confirm each li has a UL or OL parent. Ensure nested lists sit inside their parent li.
    • Screen reader check: Navigate to the section and use list shortcuts (e.g., NVDA: L/Shift+L; VoiceOver rotor: Lists). You should hear the list announcement and item count, and move item by item.
    • Keyboard check: Tab through the page. Non-interactive list items should not receive focus; only links or controls inside items should.
    • Mobile/touch check: With VoiceOver (iOS) or TalkBack (Android), navigate by lists and ensure the assistive tech announces lists and item counts.
    • Automated spot check:
    CSS
    Array.from(document.querySelectorAll('li'))
      .filter(node => !['UL','OL'].includes(node.parentElement?.tagName))
      .length === 0

    Good Example

    HTML
    <ul>
      <li>Account settings</li>
      <li>Notifications</li>
      <li>Security
        <ul>
          <li>Two-factor authentication</li>
          <li>App passwords</li>
        </ul>
      </li>
    </ul>

    Bad Example

    HTML
    <li>Step One</li>
    <li>Step Two</li>
    <li>Step Three</li>
    
    <!-- Or visually faked bullets with no list semantics -->
    <div class="bullets">- Shipping info</div>
    <div class="bullets">- Billing info</div>
    <div class="bullets">- Order review</div>

    Quick Checklist

    • Every li has a ul or ol parent (no orphan li elements).
    • Choose ul for unordered content; choose ol when order matters.
    • Nested lists are placed inside the corresponding li.
    • Do not fake bullets with CSS or characters; use real lists.
    • Avoid replacing ul/ol/li with ARIA roles unless necessary.
    • Screen readers announce lists and item counts where expected.
    • Only interactive elements inside list items receive keyboard focus.