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:

  1. Name — an accessible name that describes what the component is (e.g., "Submit", "Search", "Close menu")
  2. Role — what type of component it is (button, link, checkbox, etc.)
  3. 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

  1. Screen reader users — a <div> with a click handler is invisible. They hear nothing.
  2. Voice control users — they say "click Submit" but custom buttons without names can't be targeted
  3. 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

  1. Open DevTools (F12), go to the Accessibility panel (Elements > Accessibility tab), and inspect every interactive element on the page.
  2. For each element, verify it has a Name (accessible name), Role (button, link, checkbox, etc.), and correct State/Value (checked, expanded, pressed, etc.).
  3. 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.
  4. Open a screen reader and navigate to every interactive element. Confirm it is announced with a meaningful name, correct role, and current state.
  5. Pass: Every interactive element has an accessible name, correct role, and accurate state/value, whether through native HTML or ARIA attributes.
  6. Fail: Any interactive element is unnamed, has no role (e.g., clickable <div> without role="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.

Sources

  1. W3C WCAG 2.2 — Understanding 4.1.2
  2. axe-core: button-name
  3. MDN: ARIA Roles
  4. W3C WAI-ARIA Authoring Practices