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.
Names that break voice control versus names that work Comparison: aria-labels that replace visible text break voice commands; names that start with the visible text and add context after it work for voice and screen reader users. Names that break voice control versus names that work✗ Visible "Export", name "Download asCSV"Visible "Status ▾", name "Filter column"Visible "1 of 40", name "Pagination"Voice: "click Export" fails✓ Name "Export current view as CSV"Name "Status, filter"Name "Page 1 of 40"Voice: "click Export" works

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”.

Common data controls and 2.5.3 status Matrix of controls — row Edit buttons, column sort headers, export buttons, filter selects, pagination buttons — against typical failing names and fixed names. Common data controls and 2.5.3 statusTypical failing nameFixed namePassesEdit button"Modify INV-1042""Edit INV-1042"YesSort header"Sort by this column""Amount" + aria-sortYesExport button"Download data""Export current view"YesStatus filter"Column filter""Status filter"YesNext button"Go forward""Next page"Yes
Start with the visible word; append context.

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
How voice control matches a command Flow: the user says "click Export"; the voice software reads accessible names of visible controls; it finds a name starting with "Export"; it activates that control. How voice control matches a commandSpeech"click Export"Voice softwarereads accessible namesMatchname starts with "Export"Actionbutton activated
Voice control matches names, not pixels.

Step-by-step implementation

Permalink to "Step-by-step implementation"
  1. Find candidates. Search the codebase for aria-label on elements that also contain text, and for aria-labelledby pointing at elements other than the visible label. Run the lint sketch above on key pages.
  2. Rewrite names to start with visible text. “Edit INV-1042”, “Status filter”, “Export current view”. Keep word order identical to what is on screen.
  3. Move long help to descriptions. Instructions, counts and consequences belong in aria-describedby, which voice control ignores and screen readers read after the name.
  4. 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.
  5. 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.

Permalink to "Related"

← Back to Accessible Names & Descriptions for Data Widgets