WAI-ARIA Attributes Table

AttributeWhat it communicatesField note
aria-labelAccessible name for non-text elementsUse when visible text is absent - icon buttons
aria-labelledbyReference another element as the nameIDREF: points to visible text - stronger than aria-label
aria-describedbyReference supplementary descriptionIDREF: tooltips, hints, error messages
aria-expandedToggle state (true/false)For collapsible panels, accordions, dropdown triggers
aria-hidden="true"Hide from screen readersFor decorative content; does NOT remove from tab order
aria-live="polite"Announce dynamic changespolite waits; assertive interrupts - use sparingly
role="alert"Important time-sensitive messageImplicit aria-live=assertive - already announced
aria-current="page"Current item in a setBetter than .active class - communicates state, not just style
Reference: the MDN ARIA attributes reference. The first rule of ARIA: don't use ARIA - native HTML elements (button, nav, label) have built-in semantics that ARIA cannot replicate. ARIA is for when native HTML runs out: custom widgets, dynamic updates, and states that HTML has no element for. Bottom line: aria-label for icon buttons, aria-expanded for disclosure triggers, aria-live for dynamic updates, aria-current for navigation state - and native HTML for everything else. Related tools: semantic elements table, headings table, and attributes table.

WAI-ARIA (Web Accessibility Initiative - Accessible Rich Internet Applications) is the attribute vocabulary that makes custom widgets understandable to screen readers. The table below is the working eight - the attributes that cover real accessibility work, from icon button names to dynamic update announcements.

Bottom line: the first rule of ARIA is don't use ARIA - native HTML elements (button, nav, label) have built-in semantics that ARIA attributes cannot replicate. ARIA is for when native HTML runs out: custom widgets, dynamic updates, and states that HTML has no element for. The second rule: never change native behaviour with ARIA when a native element exists.

The honest part: ARIA attributes are promises to screen reader users. aria-expanded="true" tells the user a panel is open - if the panel doesn't actually open, the ARIA is lying. Every ARIA attribute is a contract with the user, and broken contracts are worse than no ARIA at all (which at least has no false expectations).

How to use

  1. Start with native HTML: if a button, nav, or label element exists, use it before reaching for ARIA.
  2. Add ARIA for the gaps: aria-label on icon buttons, aria-expanded on disclosure triggers, aria-live on dynamic updates.
  3. Test with a screen reader: VoiceOver (Cmd+F5 on Mac) or NVDA (free on Windows) - what you hear is what the user gets.

Frequently asked questions

What is the first rule of ARIA?

Don't use ARIA. Native HTML elements (button, nav, label, table) have built-in semantics, keyboard support and screen reader announcements that ARIA attributes cannot replicate. A <div role="button"> requires you to manually add keyboard support (Enter and Space), focus management, and role announcement - all of which <button> gives you for free. ARIA is for gaps, not replacements.

What is the difference between aria-label and aria-labelledby?

aria-label takes a string directly (aria-label="Close dialog") - use it when there is no visible text to reference. aria-labelledby takes an ID reference (aria-labelledby="heading-id") - use it when visible text already exists, because screen readers announce the REFERENCED element's text, which is more robust (updates automatically when the visible text changes). The rule: aria-labelledby when visible text exists, aria-label when it doesn't.

When should I use aria-live and what does polite vs assertive mean?

aria-live announces dynamically inserted content to screen readers without them needing to re-focus. polite waits for the current announcement to finish before reading the new content (chat messages, form success); assertive INTERRUPTS immediately (error alerts, time-critical updates). The honest advice: use polite 95% of the time, assertive only for genuinely urgent messages, and never put aria-live on content that changes every keystroke (the screen reader will read every character).

What is the difference between aria-hidden and display: none?

display: none removes the element from BOTH rendering AND the accessibility tree - screen readers cannot see it at all. aria-hidden="true" removes it from the accessibility tree but it still occupies visual space and participates in layout. The trap: aria-hidden on a focusable element is a failure - the element is invisible to screen readers but still in the tab order, creating a 'ghost' tab stop. Use hidden or display: none when you want it fully gone.

Related tools