Label in Name (2.5.3) for Data Controls
Permalink to "Label in Name (2.5.3) for Data Controls"Voice control users operate interfaces by saying what they see: “click Export”, “click Status”. If a button visibly says “Export” but its aria-label is “Download current view as CSV”, saying “click Export” does nothing. SC 2.5.3 Label in Name requires the accessible name to contain the visible text, and best practice is for it to start with it. Data interfaces break this rule constantly, usually while trying to add helpful context for screen reader users.
This guide belongs to accessible names and descriptions for data widgets.
Spec reference
Permalink to "Spec reference"- SC 2.5.3 Label in Name (A) — for components with visible text labels, the accessible name contains the visible text; starting with it is best practice.
- SC 4.1.2 (A) — names must be programmatically determinable.
- SC 2.4.6 Headings and Labels (AA) — labels describe purpose.
- Voice control software — Dragon, Voice Control (macOS/iOS) and Voice Access (Android) match spoken words to accessible names.
When to use — and when not to
Permalink to "When to use — and when not to"Apply this check to every control with visible text: buttons, links, column header buttons, tabs, menu items, filter chips and form fields. Icon-only controls are not covered by 2.5.3 but should use names matching their tooltips.
Do not “fix” 2.5.3 by deleting useful context; move it after the visible text or into a description. The misapplication: naming each row’s “Edit” button “Modify invoice record INV-1042”, which contains no “Edit”.
Annotated code example
Permalink to "Annotated code example"<!-- Fails: aria-label replaces the visible "Edit" -->
<button aria-label="Modify invoice INV-1042">Edit</button>
<!-- Passes: name starts with visible text, adds context -->
<button aria-label="Edit INV-1042">Edit</button>
<!-- Alternative: visually hidden suffix keeps visible text first -->
<button>Edit<span class="sr-only"> INV-1042</span></button>
<!-- Extra help goes in a description, not the name -->
<button aria-describedby="export-help">Export</button>
<p id="export-help" class="hint">Exports the 84 filtered rows as CSV.</p>
// Lint rule sketch: visible text must be a prefix of the accessible name
for (const el of document.querySelectorAll('button, a, [role=button], [role=tab], [role=menuitem]')) {
const visible = el.innerText.trim().toLowerCase();
const name = (el.getAttribute('aria-label') || visible).toLowerCase();
if (visible && !name.startsWith(visible)) console.warn('2.5.3', el, { visible, name });
}
Keyboard & AT behaviour
Permalink to "Keyboard & AT behaviour"| User | Says or hears | Result with fixed names |
|---|---|---|
| Dragon user | “Click Edit” | Numbered overlays for each Edit button |
| Voice Control (macOS) | “Click Export” | Export activates |
| Screen reader user | Tab to Edit | “Edit INV-1042, button” |
| Speech-to-text user | “Show numbers” then a number | Works either way |
Step-by-step implementation
Permalink to "Step-by-step implementation"- Find candidates. Search the codebase for
aria-labelon elements that also contain text, and foraria-labelledbypointing at elements other than the visible label. Run the lint sketch above on key pages. - Rewrite names to start with visible text. “Edit INV-1042”, “Status filter”, “Export current view”. Keep word order identical to what is on screen.
- Move long help to descriptions. Instructions, counts and consequences belong in
aria-describedby, which voice control ignores and screen readers read after the name. - Handle symbols and abbreviations. If a button shows “CSV ↓”, its name can be “CSV download”; avoid names that spell the symbol in a way users would not say.
- Test with voice. Use Voice Control on macOS or Voice Access on Android and say each visible label on a typical page.
Integration context
Permalink to "Integration context"Icon button naming is covered in naming icon-only row action buttons, and descriptions in aria-describedby for column help text. Voice testing of grids is described in voice control testing for data grids. Automated checks are in automated accessibility testing pipelines.
Gotchas
Permalink to "Gotchas"Tooltips as visible labels. For icon buttons, the tooltip text is effectively the visible label; make the name match it.
Translations. Translated aria-labels often drift from translated visible text; generate both from one string.
Case and punctuation. Matching is case-insensitive in practice, but punctuation inside words (“Re-run”) can break matches; keep it identical.
Edge cases
Permalink to "Edge cases"- Headings inside buttons. Expanders whose visible text is a heading should use that heading text as the name.
- Counts in labels. “Filters (3)”: the name “Filters, 3 applied” still starts with “Filters”.
- Images of text. Logos or text in images need alt text matching the visible words.
Worked example
Permalink to "Worked example"A reporting tool’s toolbar had visible buttons “Export”, “Share” and “Schedule”, with aria-labels written by a well-meaning developer: “Download report”, “Send to colleagues” and “Set up recurring delivery”. Dragon users saying “click Export” got nothing. The team changed names to “Export report”, “Share report” and “Schedule report”, moved the longer explanations into descriptions and added a lint check in CI. Voice control commands worked on the first attempt.
Common mistakes
Permalink to "Common mistakes"- aria-label that replaces visible text.
- Context placed before the visible word.
- Different strings for visible and accessible text in translations.
- Fixing by removing useful context entirely.
Testing checklist
Permalink to "Testing checklist"Testing it with a screen reader
Permalink to "Testing it with a screen reader"Although 2.5.3 is mainly about voice control, a screen reader is a quick way to hear names. Tab through a toolbar with NVDA and compare each spoken name with what you see; any name that starts with a different word is a likely failure. Then turn on Voice Control on macOS, say “show names” to overlay accessible names on controls, and say “click” followed by each visible label. On Android, use Voice Access with “show labels”. Record which controls failed and fix the names at their source.
Design system notes
Permalink to "Design system notes"Give components a label prop for visible text and a separate context prop that is appended to the accessible name, so the name always starts with the label by construction.
FAQ
Permalink to "FAQ"Does the name have to match exactly?
It must contain the visible text; starting with it is strongly recommended.
Do icon-only buttons fall under 2.5.3?
Not strictly, but match their tooltips for voice users.
Is aria-labelledby safer than aria-label?
Pointing aria-labelledby at the visible text guarantees a match; add context with additional IDs after it.
What about form fields?
The label element text should be the start of the field’s name; placeholders are not labels.
How common are these failures in data UIs?
Very common in toolbars, row actions and grid headers, where developers add context.
Does this help anyone besides voice users?
Yes. Consistent names help screen reader users who can see the screen and cognitive users who follow on-screen instructions.
Related
Permalink to "Related"- Naming icon-only row action buttons — names for icon controls
- Voice control testing for data grids — testing with voice
- aria-describedby for column help text — where extra context goes