Skip to main content
Robust WCAG 4.1.2

4.1.2 Name, Role, Value

For all user interface components, the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies.

Level A Critical WCAG 2.0 (new) WCAG 2.1 WCAG 2.2
button-name aria-label aria-labelledby aria-hidden-body aria-hidden-focus aria-valid-attr aria-valid-attr-value aria-allowed-attr aria-allowed-role aria-roles

What this rule means

WCAG 4.1.2 Name, Role, Value is one of the most broadly applicable accessibility criteria. It requires that every interactive user interface component exposes three things to assistive technology: its name (what it is called), its role (what type of control it is), and its current value or state (what it is set to or whether it is expanded, checked, selected, etc.).

Native HTML elements such as <button>, <input>, <select>, and <a> automatically expose their role and allow names to be set via labels, text content, or attributes. The criterion becomes critical when developers build custom widgets — dropdown menus, tab panels, accordions, date pickers, sliders — using generic elements like <div> and <span>. Without explicit ARIA attributes, these custom components are invisible or meaningless to screen readers.

The "value" component also requires that state changes are communicated. When a user expands an accordion, the assistive technology must be notified that the section is now open. When a checkbox is toggled, the checked state must update in the accessibility tree, not just visually.

Why it matters

Screen reader users interact with a page through the accessibility tree, not the visual layout. When a custom dropdown built from <div> elements lacks role="listbox" and aria-expanded, a screen reader announces it as a generic group or plain text. The user has no way to know it is interactive, what options it contains, or which option is selected. They are effectively locked out of the interface.

This criterion is rated critical impact because failures directly prevent task completion. A button without a name cannot be identified. A custom checkbox without aria-checked cannot convey its state. A tab interface without role="tablist" and role="tab" cannot be navigated. These are not cosmetic issues — they represent complete barriers for assistive technology users.

The proliferation of JavaScript frameworks and component libraries has made 4.1.2 failures one of the most common accessibility issues on the web. The WebAIM Million annual study consistently finds missing button names, missing form labels, and ARIA misuse among the top five most common errors.

Related axe-core rules

  • button-name — Ensures buttons have discernible, accessible text.
  • aria-label — Verifies aria-label values are not empty.
  • aria-labelledby — Ensures aria-labelledby references existing element IDs.
  • aria-hidden-body — Ensures aria-hidden="true" is not present on the <body> element.
  • aria-hidden-focus — Ensures elements hidden with aria-hidden do not contain focusable children.
  • aria-valid-attr — Ensures ARIA attribute names are valid and correctly spelled.
  • aria-valid-attr-value — Ensures ARIA attribute values are valid for their type.
  • aria-allowed-attr — Ensures ARIA attributes are appropriate for the element's role.
  • aria-allowed-role — Ensures the role attribute is valid for the element it is placed on.
  • aria-roles — Ensures all role attribute values are valid ARIA roles.

How to test

Testing for 4.1.2 requires a combination of automated and manual techniques. Automated tools can catch missing names, invalid ARIA attributes, and incorrect roles, but they cannot judge whether the name is meaningful or whether state changes are properly communicated.

  1. Run axe-core or Lighthouse and review all findings in the "ARIA" and "Names and Labels" categories.
  2. Open the browser's accessibility inspector (Chrome DevTools > Elements > Accessibility pane) and verify that each interactive element shows a correct Name, Role, and State.
  3. Tab through the page and use arrow keys within composite widgets. Confirm that the screen reader announces the role (button, tab, listbox item, etc.), the name, and the current state (expanded, selected, checked).
  4. Toggle states — expand accordions, check boxes, select tabs — and verify the screen reader announces the change.
  5. Inspect custom components built with <div> or <span>. Confirm they have appropriate ARIA roles, names, and state attributes.

How to fix

The golden rule: use native HTML elements whenever possible. When custom components are necessary, provide complete ARIA semantics.

Buttons without names — bad practice

<!-- Icon button with no accessible name -->
<button>
  <svg viewBox="0 0 24 24"><path d="M3 18h18v-2H3v2z"/></svg>
</button>

<!-- Button with only whitespace text -->
<button>   </button>

<!-- Div acting as button with no role or name -->
<div onclick="save()">Save</div>

Buttons — good practice

<!-- Icon button with aria-label -->
<button aria-label="Open menu">
  <svg aria-hidden="true" viewBox="0 0 24 24">
    <path d="M3 18h18v-2H3v2z"/>
  </svg>
</button>

<!-- Button with visible text -->
<button type="button">Save Document</button>

<!-- If you must use a div (not recommended), add role and tabindex -->
<div role="button" tabindex="0" onclick="save()" onkeydown="handleKey(event)">
  Save
</div>

Custom checkbox — bad practice

<!-- Div styled as checkbox but invisible to AT -->
<div class="checkbox checked" onclick="toggle()">
  <span class="checkmark">✓</span>
  Accept terms
</div>

Custom checkbox — good practice

<!-- Native checkbox (preferred) -->
<label>
  <input type="checkbox" name="terms" checked>
  Accept terms
</label>

<!-- Custom checkbox with full ARIA -->
<div
  role="checkbox"
  aria-checked="true"
  aria-label="Accept terms"
  tabindex="0"
  onclick="toggle()"
  onkeydown="handleKey(event)"
>
  <span class="checkmark" aria-hidden="true">✓</span>
  Accept terms
</div>

Tab interface — complete pattern

<div role="tablist" aria-label="Project settings">
  <button role="tab" id="tab-general" aria-selected="true" aria-controls="panel-general">
    General
  </button>
  <button role="tab" id="tab-members" aria-selected="false" aria-controls="panel-members" tabindex="-1">
    Members
  </button>
</div>

<div role="tabpanel" id="panel-general" aria-labelledby="tab-general">
  <p>General settings content here.</p>
</div>

<div role="tabpanel" id="panel-members" aria-labelledby="tab-members" hidden>
  <p>Members settings content here.</p>
</div>

Accordion with state management

<h3>
  <button aria-expanded="true" aria-controls="section1-content">
    Billing Information
  </button>
</h3>
<div id="section1-content" role="region" aria-labelledby="section1-heading">
  <p>Your current plan is Professional.</p>
</div>

<h3>
  <button aria-expanded="false" aria-controls="section2-content">
    Payment History
  </button>
</h3>
<div id="section2-content" role="region" aria-labelledby="section2-heading" hidden>
  <p>Payment records will appear here.</p>
</div>

Invalid ARIA — common errors

<!-- Bad: misspelled ARIA attribute -->
<button aria-labelled="Save">Save</button>

<!-- Bad: invalid role value -->
<div role="buttn">Click me</div>

<!-- Bad: aria-checked on an element without checkbox/switch role -->
<div role="button" aria-checked="true">Toggle</div>

<!-- Good: correct attribute and role usage -->
<button aria-label="Save document">Save</button>
<div role="button" tabindex="0">Click me</div>
<div role="switch" aria-checked="true" tabindex="0">Toggle</div>

Common mistakes

  • Using <div> or <span> for interactive elements without adding role, tabindex, and keyboard handlers.
  • Setting aria-label to an empty string — this effectively gives the element a blank name.
  • Adding aria-hidden="true" to elements that contain focusable children — screen readers lose focus tracking.
  • Using invalid ARIA role values (e.g., role="list-item" instead of role="listitem").
  • Forgetting to update aria-expanded, aria-checked, or aria-selected when the visual state changes.
  • Overriding native semantics unnecessarily — adding role="button" to a <button> is redundant but adding role="link" to a <button> is misleading.
  • Using aria-label on non-interactive elements where it may be ignored by some screen readers.
  • Placing ARIA attributes that are not allowed for a given role — for example, aria-pressed on role="link".

Resources