Robust · Level A · 4.1.2
Name, Role, Value
Every UI component needs a name, a role, and — where applicable — a state or value that assistive technology can read and, where the user can change it, update.
- Blind
- Low vision
- Motor
How to recognize it
Web design keeps getting more visually polished and more feature-rich, and that makes it easy to drift away from the plain, recognizable HTML elements the browser already understands and knows how to adapt for the user. Instead of a native element, teams reach for a generic <div> or <span> to get an exact visual result — and that generic element hides the very functionality browsers would otherwise expose automatically. To check for it: turn off the mouse and tab through the page, or turn on a screen reader. A <div> styled to look like a button that does nothing when you tab to it and press Enter is failing. A custom checkbox or toggle that a screen reader reads only as 'clickable' with no indication of on/off is failing. A custom dropdown that never announces whether it's open or closed is failing. Note the difference from 2.4.4 (Link Purpose): there, a name exists but is ambiguous; here, there's often no name — or no role, or no state — at all.
How to fix it
Use the native HTML element for the job — <button>, <input type="checkbox">, <select> — whenever you can; it gets the correct role, an accessible name from its label, keyboard support, and state handling for free, with zero extra code. When a custom widget is genuinely unavoidable (a design system component, a widget with no native equivalent), you have to build all of that back by hand: an ARIA role (role="checkbox", role="combobox"...), an accessible name (visible text, aria-label, or aria-labelledby), keyboard support (tabindex plus your own Enter/Space handlers), and state attributes you update with JavaScript every time the state changes (aria-checked, aria-expanded, aria-pressed).
Example
Avoid
<div class="btn" onclick="submitForm()">Submit</div><span class="checkbox" onclick="toggle(this)"></span> Email me updates<div class="icon-btn" onclick="closeModal()"><svg>...</svg></div>Prefer
<button onclick="submitForm()">Submit</button><input type="checkbox" onchange="toggle(this)" id="updates"> <label for="updates">Email me updates</label><button aria-label="Close dialog" onclick="closeModal()"><svg>...</svg></button>