WCAG 4.1.2: Name, Role, Value
For every user-interface component, the name and role must be programmatically determinable, the states, properties, and values the user can set must be programmatically settable, and any change must be announced to assistive technologies. This Level A criterion is the contract between your interface and screen readers — and the single most-failed success criterion on the web.
The success criterion, in full
For all user interface components (including but not limited to: form elements, links and components generated by scripts), 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.
Why name, role, and value matter
Sighted users read an interface visually: a magnifying-glass icon reads as “search”, a pill that looks pushed-in reads as “on”, an underlined word reads as “a link”. A screen reader user gets none of that visual styling. They rely entirely on the accessibility tree— a parallel structure the browser builds from your HTML and ARIA, exposing each control's name, role, state, and value to assistive technology. WCAG 4.1.2 is the requirement that this tree is complete and accurate.
When it is not, controls become unusable. An icon button with no accessible name is announced as just “button” — the user cannot tell what it does. A custom toggle built from a <div> is announced as plain text — the user does not know it is interactive, cannot reach it with the keyboard, and never hears whether it is on or off. These are not edge cases: they are the most frequent accessibility errors on the web.
4.1.2 sits under Principle 4, Robust — content must work reliably with the widest range of user agents and assistive technologies, now and as they evolve. Exposing a correct name, role, and value is how you keep that promise across NVDA, JAWS, VoiceOver, TalkBack, and tools that do not exist yet.
Name, role, state, and value explained
The criterion bundles four things every interactive component must expose. Native HTML supplies most of them automatically; you only hand-wire them when you build a custom widget.
Name
The accessible name — what a screen reader announces to identify the control.
Every interactive component needs a programmatically determinable name that conveys its purpose. A button that closes a dialog needs the name “Close”; a search field needs the name “Search”. The browser computes this name from sources such as a <label>, the element's text content, an aria-label, or an aria-labelledby reference. An icon-only button with no text and no label has an empty accessible name, which fails 4.1.2.
Role
What kind of component it is — button, link, checkbox, tab, dialog.
The role tells assistive technology how the component behaves and how the user can operate it. Native elements expose their role automatically: a <button> has the role “button”, an <a href> has the role “link”. When you build a control from a generic <div> or <span>, it has no implied role, so you must supply one with the role attribute — and then re-implement all the keyboard and state behavior the native element gave you for free.
State
The current condition of the component — pressed, checked, expanded, selected, disabled.
States change as the user interacts. A toggle button is pressed or not pressed (aria-pressed); a disclosure is expanded or collapsed (aria-expanded); a checkbox is checked or unchecked. States must be programmatically determinable and must update as they change so a screen reader announces the new state. A visual-only state change — for example, a button that merely changes color — is invisible to assistive technology.
Value & Properties
The component's current value and any extra properties assistive tech needs.
Components that hold a value must expose it: a slider exposes aria-valuenow/min/max, a combobox exposes its selected text. Properties describe relationships and constraints that do not change as often as states — aria-required, aria-haspopup, aria-controls, or aria-describedby pointing at help text. Together, name, role, state, value, and properties give assistive technology a complete, accurate picture of the control.
How the accessible name is computed
The browser derives an element's accessible name by running the accessible name computation — checking several sources in priority order and using the first one that produces a non-empty string. Knowing the order tells you exactly which markup wins:
- 1
aria-labelledbyPoints at the id(s) of other element(s) whose text becomes the name. Highest priority — it overrides everything below, including visible text.
- 2
aria-labelA string you supply directly. Common for icon-only buttons. Overrides native labels and content, so use it deliberately.
- 3
Native label / element contentA <label> associated with a form control, or the element's own text content (a button's text, a link's text). This is the default and the most robust source.
- 4
title / placeholder (last resort)Used only when nothing above exists. Unreliable — title is hidden from many users and placeholder disappears on input — so never rely on them as the primary name.
A practical rule follows from this order: prefer a visible label or visible text content, because it names the control for everyone and keeps the accessible name in sync with what sighted users see. Reserve aria-label for controls that have no visible text, like icon buttons. For more on the attributes themselves, see the ARIA Attributes Reference and our guide to ARIA labels.
Code examples
Native element vs. fake button
The clickable <div> has no role, no name, no keyboard support, and no focus. The native <button> supplies all of them for free.
<!-- FAILS 4.1.2: no role, no name, not focusable, no keyboard -->
<div class="btn" onclick="save()">
<svg aria-hidden="true">...</svg>
</div>
<!-- PASSES: real button + accessible name for the icon -->
<button type="button" onclick="save()">
<svg aria-hidden="true" focusable="false">...</svg>
<span class="visually-hidden">Save document</span>
</button>
<!-- Or name an icon-only button with aria-label -->
<button type="button" aria-label="Save document" onclick="save()">
<svg aria-hidden="true" focusable="false">...</svg>
</button>Form field with a programmatic name
A placeholder is not a label. Associate a real <label> so the field has an accessible name that persists once the user starts typing.
<!-- FAILS 4.1.2: placeholder is not an accessible name -->
<input type="email" placeholder="Email address" />
<!-- PASSES: label is programmatically associated via for/id -->
<label for="email">Email address</label>
<input type="email" id="email" name="email" />Custom toggle button that announces its state
A toggle needs a role, a name, and a statethat updates so the screen reader announces “pressed” or “not pressed”. Using a native <button> with aria-pressed is the robust pattern.
function MuteToggle() {
const [muted, setMuted] = useState(false)
return (
<button
type="button"
// role "button" comes free from the native element
aria-pressed={muted} // state, announced on change
aria-label={muted ? "Unmute" : "Mute"} // name reflects the action
onClick={() => setMuted((m) => !m)}
>
<VolumeIcon aria-hidden="true" />
</button>
)
}Disclosure with state and relationship
aria-expanded exposes the open/closed state; aria-controls exposes the relationship to the region it shows and hides.
<button
type="button"
aria-expanded="false" // state: collapsed -> updates to "true" on open
aria-controls="faq-1" // property: points at the controlled region
>
Shipping & returns
</button>
<div id="faq-1" hidden>...</div>Common mistakes
- Icon-only buttons and links with no accessible name — a screen reader announces just “button” or “link”. Add visible text, a visually-hidden label, or aria-label.
- Using a placeholder as the only label. Placeholders disappear on input, fail contrast, and are not a reliable accessible name. Use a real <label>.
- Building interactive controls from <div> or <span> with onClick — no role, no focus, no keyboard. Use a native <button> or <a href> instead.
- Setting a role but never updating the state. A custom toggle with role but no aria-pressed update never tells the user it changed.
- Linked images with no alt text, producing an empty link whose name is just the URL or nothing. Give the image alt text that describes the link's destination.
- Overriding a good visible name with a mismatched aria-label, so the visible text and the announced name disagree — confusing for voice-control users (see 2.5.3 Label in Name).
- Adding redundant ARIA to native elements (role="button" on a <button>), which adds risk without benefit. Native semantics already satisfy 4.1.2.
How to test for 4.1.2
- 1
Inspect the accessibility tree
Open DevTools and use the Accessibility panel (Chrome, Firefox, Edge). For each interactive element, confirm the computed Name is meaningful, the Role is correct, and the states reflect the current condition.
- 2
Tab through every control
Press Tab and check that every interactive element receives focus. Anything you can click with a mouse but cannot reach with the keyboard usually has the wrong role or none at all.
- 3
Run an automated scanner
axe DevTools and Lighthouse reliably flag empty buttons, links with no name, and form fields with no label — the bulk of 4.1.2 failures — across a page at once.
- 4
Listen with a screen reader
With NVDA or VoiceOver, move to each control and confirm it announces a sensible name, role, and state. Toggle controls and verify the new state (pressed, expanded, checked) is announced.
- 5
Check state changes are announced
Activate toggles, accordions, and tabs and confirm the change is reported — not just visually shown. Silent state changes are the most missed part of 4.1.2.
Audit a live page with the URL Accessibility Auditor, generate correct labels with the Accessibility Code Generator, and follow the full process in our Screen Reader Testing guide.
Related success criteria
1.3.1 Info and Relationships — A
Structure and relationships must be programmatically determinable too. 4.1.2 names the controls; 1.3.1 exposes how they relate to labels, groups, and regions.
1.1.1 Non-text Content — A
Alt text on a linked image is what gives that link its accessible name. Empty alt on a functional image is both a 1.1.1 and a 4.1.2 failure.
2.1.1 Keyboard — A
A correct role is only useful if the control is operable. Custom widgets must be focusable and keyboard-operable as well as correctly named.
4.1.3 Status Messages — AA
The sibling criterion for messages that are not tied to a control — using ARIA live regions so updates are announced without moving focus.
Frequently asked questions
What does WCAG 4.1.2 Name, Role, Value require?
WCAG 4.1.2 requires that for every user-interface component — links, form controls, buttons, custom widgets — the name and role can be programmatically determined; states, properties, and values that the user can set can be programmatically set; and any changes to those items are made available to assistive technologies such as screen readers. In plain terms: assistive tech must be able to tell what each control is (role), what it is called (name), and its current condition (state/value), and must be notified when those change. It is a Level A success criterion, the most foundational conformance level.
What is the difference between an accessible name and a label?
A label is one possible source of the accessible name; the accessible name is the final computed string a screen reader announces. The browser runs an algorithm called the accessible name computation that looks at several sources in priority order — aria-labelledby first, then aria-label, then the native label (a <label> element or the element's own text content), then attributes such as title or placeholder as a last resort. The string it produces is the accessible name. So a form field labeled with a <label>, an icon button named with aria-label, and a link named by its text content all end up with an accessible name, just computed from different sources.
Do native HTML elements satisfy 4.1.2 automatically?
Native interactive elements give you the correct role and the built-in state and value handling for free, which is most of 4.1.2 — a <button>, <a href>, <input>, <select>, and <textarea> all expose a proper role and report their states and values to assistive technology without any ARIA. You still have to provide an accessible name: a visible <label> for form fields, visible text or aria-label for buttons and links. The guidance is to use native elements first and only reach for ARIA when no native element does the job, because hand-built widgets must re-create every behavior the browser would have handled.
Why is 4.1.2 the most commonly failed WCAG criterion?
Because it is failed by the most frequent real-world defects: unlabeled form fields, empty links (a linked icon or image with no alt text or accessible name), and buttons with no text. The annual WebAIM Million analysis of the top one million home pages consistently finds missing form labels, empty links, and empty buttons among the most common accessibility errors — and all three are 4.1.2 (and often 1.1.1 or 1.3.1) failures. Custom JavaScript widgets built from <div> and <span> without roles, names, or state attributes are another major source.
Is using a div with an onClick handler a 4.1.2 failure?
By itself, yes. A clickable <div> has no role (assistive tech does not know it is a button), usually no accessible name, no keyboard operability, and no focus. To make it pass you would need role="button", an accessible name, tabindex="0", and key handlers for Enter and Space — at which point you have manually rebuilt a native <button>. The accessible, robust, and far simpler fix is to use a real <button> element, which provides the role, focusability, and keyboard activation automatically.
How do I test for WCAG 4.1.2?
Inspect the accessibility tree in your browser DevTools (the Accessibility panel in Chrome, Firefox, or Edge) and confirm each interactive element shows the correct role, a meaningful name, and accurate states. Run an automated scanner such as axe DevTools or Lighthouse to catch empty buttons, unlabeled fields, and missing names at scale. Then verify with a real screen reader — NVDA or VoiceOver — by tabbing through every control and confirming it announces a sensible name, role, and current state, and that toggling a control announces the new state.