ADA Compliance Professionals

    ARIA role values must be valid and never abstract roles

    Last updated:

    Who it helps:
    Blind
    Standard:
    WCAG 2.2 Level A

    Elements must not use invalid or abstract ARIA role values

    Only valid, non-abstract ARIA role values are allowed in the role attribute.

    This affects any element using role="...", especially custom components built with div or span.

    People using screen readers, voice control, and other assistive tech rely on correct roles to understand and operate the interface.

    Why It Matters

    If the role value is unknown or abstract, assistive technologies cannot expose the correct widget type or landmark. Users may not find navigation regions, understand states, or know how to interact.

    Invalid roles can remove items from landmark lists, break rotor/quick nav, and cause keyboard or screen reader commands to fail.

    This impacts blind users (screen readers), motor-impaired users (voice control and switch access), and some cognitive users who depend on consistent structure.

    Common Causes

    • Typographical errors (e.g., role="naviation" or role="buton").
    • Using abstract roles (e.g., role="command", role="composite").
    • Wrong case or formatting (roles are lowercase tokens).
    • Assigning deprecated or non-existent roles.
    • Forcing roles where native HTML already provides semantics, leading to conflicts.
    • Stacking multiple unrelated role tokens where only one should apply.

    How to Fix

    1. Inventory role usage:
      • Search your templates and components for role="...".
      • Note where roles are applied to non-semantic elements (div, span) and to complex widgets.
    2. Validate the value:
      • Confirm each value exists in the current WAI-ARIA specification (e.g., navigation, main, banner, contentinfo, region, button, link, tab, tablist, tabpanel, status, alert, tooltip, tree, treeitem, grid, row, rowheader, columnheader, checkbox, radio, radiogroup, listbox, option, combobox, slider, progressbar, separator, spinbutton, toolbar, dialog, alertdialog, form, search, article, complementary, img, heading, listitem, menu, menubar, menuitem, menuitemcheckbox, menuitemradio, log, timer, status, note, definition, math, document, application, presentation).
      • Do not use abstract roles (e.g., command, composite, input, landmark, range, section, select, structure, widget).
    3. Prefer native HTML:
      • Use semantic elements (nav, main, header, footer, button) instead of adding roles when possible.
      • Add a landmark role only when the native element is unavailable or insufficient.
    4. Match role to purpose and context:
      • Landmark roles must identify page regions (e.g., role="navigation" with an aria-label when there are multiple navs).
      • Widget roles must include required ARIA states/props and keyboard behavior for that widget.
    5. Use correct syntax:
      • Roles are lowercase and space-separated tokens. Use a single role unless you intentionally provide a fallback role pattern (advanced use). Remove stray or conflicting tokens.
    6. Avoid risky roles unless you fully implement them:
      • role="application" changes AT behavior; use sparingly around a well-implemented widget only.
      • role="presentation"/"none" must not be used on focusable or interactive elements.
    7. Re-test after changes:
      • Verify the computed role in browser devtools (Accessibility pane) and with screen readers.

    How to Test

    Keyboard check:

    • Navigate to each component that has a role.
    • Ensure the control behaves as the announced role implies (e.g., a role="button" activates with Enter/Space).

    Screen reader check:

    • With NVDA/JAWS (Windows) or VoiceOver (macOS), navigate landmarks and widgets.
    • Confirm the element is announced with the expected role (e.g., "navigation", "status", "tab").
    • Ensure abstract or unknown roles are not announced.

    Mobile/touch check:

    • VoiceOver (iOS) Rotor or TalkBack (Android) quick navigation should list landmarks and widgets.
    • Verify regions appear with correct names if multiple of the same type exist (aria-label or aria-labelledby).

    Simple checklist:

    • No misspellings; roles are valid ARIA tokens in lowercase.
    • No abstract roles anywhere.
    • Landmarks and widgets announce correctly in the accessibility tree.
    • Native HTML used where possible; roles only added when needed.
    • No conflicting or redundant multiple roles.

    Good Example

    HTML
    <div role="navigation" aria-label="Primary">
      <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/products">Products</a></li>
        <li><a href="/contact">Contact</a></li>
      </ul>
    </div>
    
    <div role="status" aria-live="polite">Settings saved</div>

    Why it’s good:

    • Uses valid roles (navigation, status).
    • Landmark is named so multiple navs can be distinguished.
    • Roles match intent and are recognized by AT.

    Bad Example

    HTML
    <div role="nav" aria-label="Primary">
      ...
    </div>
    
    <div role="command">Settings saved</div>

    What’s wrong:

    • role="nav" is not a valid ARIA role (typo/unknown).
    • role="command" is an abstract role and must not be used.
    • Both elements will have unreliable or missing semantics in AT.

    Quick Checklist

    • Only valid, lowercase ARIA role values are used.
    • No abstract roles (command, composite, input, etc.).
    • Prefer semantic HTML; add roles only when necessary.
    • Roles align with the component’s behavior and required ARIA attributes.
    • Avoid role="application" unless you fully implement a complex widget.
    • Do not use role="presentation"/"none" on focusable or interactive elements.
    • Verify computed roles in the accessibility tree and with screen readers.
    • Keep one clear role per element; remove stray or conflicting tokens.