Every colored region below represents a landmark. Screen reader users can jump directly between them. Click any region to see which HTML element or role created it, and whether the role attribute is needed.
HTML5 semantic element = no role needed. Div or span = role required. Adding role="navigation" to a <nav> is redundant noise in the accessibility tree.
Each widget below uses the correct ARIA role + keyboard interaction. Try navigating each with only the keyboard — Tab to reach, then use the widget's specific keys.
Both buttons below try to announce a message. The first creates the live region and injects content simultaneously (broken). The second injects into a pre-existing live region (correct). Watch the SR Announcement box.
Type in the textarea. The counter updates visually and announces to screen readers. aria-atomic="true" ensures the full "X characters remaining" phrase is read, not just the number.
The WAI-ARIA Authoring Practices Guide defines 5 rules. Here's what each violation looks like vs the correct pattern. Click any rule to expand.
Backed by WebAIM's 2025 analysis showing that sites with ARIA present have more than twice as many errors as sites without ARIA. Click each to see the mistake and fix.
Adding role="button" to a <button>, or role="navigation" to a <nav> creates duplicated noise in the accessibility tree without adding any value.
When focus lands inside an aria-hidden="true" container, the screen reader announces nothing. The user has no idea where they are — a completely silent experience.
role="menu" is for application menus (File, Edit, View). Navigation dropdowns should use no menu role — just aria-expanded on the trigger and plain links in the dropdown.
The accessibility API must register the live region while empty. Creating a live region and injecting content simultaneously causes no announcement at all.
When a dropdown opens or closes, aria-expanded on the trigger button must be updated. Screen readers announce "expanded" or "collapsed" — without this, users can't tell the state changed.
aria-label on a plain <div> or <p> has no effect — these elements have no role that would surface the label. Labels are only meaningful on interactive elements and landmark/grouping roles.
Open DevTools → Accessibility pane and check three things on every interactive element: (1) Is it in the tree? (2) Does it have the right role? (3) Does it have an accessible name? Fix all three before opening a screen reader.