4.1.2 Name, Role, Value
Level: A | Principle: Robust | Since: WCAG 2.0 | Automation: Partial (axe-core)
What This Means
Every user interface component must have:
- Name — an accessible name that describes what the component is (e.g., "Submit", "Search", "Close menu")
- Role — what type of component it is (button, link, checkbox, etc.)
- Value/State — its current state (checked, expanded, selected, disabled, etc.)
Native HTML elements get this automatically. Custom components built with <div> and <span> do not — they need ARIA attributes.
Who This Affects
- Screen reader users — a
<div>with a click handler is invisible. They hear nothing. - Voice control users — they say "click Submit" but custom buttons without names can't be targeted
- Switch device users — they rely on programmatic roles to navigate
Common Pitfalls
1. Buttons with no text
<!-- Bad: empty button -->
<button></button>
<!-- Bad: icon button with no label -->
<button><svg><!-- icon --></svg></button>
<!-- Good -->
<button aria-label="Close">
<svg aria-hidden="true"><!-- close icon --></svg>
</button>
2. Clickable divs instead of buttons
<!-- Bad: div acting as button -->
<div onclick="handleClick()">Save</div>
<!-- Good: native button -->
<button onclick="handleClick()">Save</button>
<!-- Acceptable: ARIA role + tabindex + keyboard handler -->
<div role="button" tabindex="0"
onclick="handleClick()"
onkeydown="if(event.key==='Enter') handleClick()">
Save
</div>
3. Custom select/dropdown without ARIA
<!-- Bad: custom dropdown with no ARIA -->
<div class="dropdown">
<div class="selected">Choose one</div>
<ul class="options">
<li>Option A</li>
<li>Option B</li>
</ul>
</div>
<!-- Good: with ARIA -->
<div role="listbox" aria-label="Choose one" aria-expanded="false">
<div role="option" aria-selected="true">Option A</div>
<div role="option" aria-selected="false">Option B</div>
</div>
4. Toggle buttons without state
<!-- Bad: no indication of toggle state -->
<button>Dark mode</button>
<!-- Good: aria-pressed communicates state -->
<button aria-pressed="false">Dark mode</button>
How to Fix
Rule of thumb: Use native HTML elements whenever possible. They have built-in names, roles, and states.
| Instead of | Use |
|-----------|-----|
| <div onclick> | <button> |
| <span> as link | <a href> |
| Custom checkbox | <input type="checkbox"> |
| Custom select | <select> |
When you must use custom elements, add ARIA:
<!-- Custom button -->
<div role="button" tabindex="0" aria-label="Save changes">Save</div>
<!-- Custom checkbox -->
<div role="checkbox" tabindex="0" aria-checked="false" aria-label="Agree to terms">
<span>☐</span> I agree
</div>
<!-- Expandable section -->
<button aria-expanded="false" aria-controls="details">
Show details
</button>
<div id="details" hidden>...</div>
How to Test
- Open DevTools (F12), go to the Accessibility panel (Elements > Accessibility tab), and inspect every interactive element on the page.
- For each element, verify it has a Name (accessible name), Role (button, link, checkbox, etc.), and correct State/Value (checked, expanded, pressed, etc.).
- Check custom interactive elements (divs with click handlers, custom dropdowns, toggle buttons) for proper ARIA attributes:
role,tabindex,aria-label,aria-expanded,aria-pressed,aria-checked. - Open a screen reader and navigate to every interactive element. Confirm it is announced with a meaningful name, correct role, and current state.
- Pass: Every interactive element has an accessible name, correct role, and accurate state/value, whether through native HTML or ARIA attributes.
- Fail: Any interactive element is unnamed, has no role (e.g., clickable
<div>withoutrole="button"), or has incorrect state information.
axe-core Rules
| Rule | What It Checks |
|------|---------------|
| button-name | Buttons must have discernible text |
| link-name | Links must have discernible text |
| label | Form inputs must have labels |
| select-name | Select elements must have labels |
| input-button-name | Input buttons must have discernible text |
| aria-roles | ARIA roles must be valid |
| aria-valid-attr | ARIA attributes must be valid |
| aria-valid-attr-value | ARIA attribute values must be valid |
| aria-required-attr | Required ARIA attributes must be present |
| aria-hidden-focus | Focusable elements must not be inside aria-hidden |
| nested-interactive | Interactive elements must not be nested |
Tools
Test this criterion with the ARIA Validator.