The accessible name of a control must contain its visible text, so voice users can say what they see. Examples from civic forms.
People who control a device by voice read the label on screen and speak it: "click Reserve". The software looks for a control whose accessible name matches. WCAG 2.1 success criterion 2.5.3 says that for components with a visible text label (or an image of text), the accessible name must contain the visible text. The name can be longer. Best practice is to start it with the visible words.
Capitalization and most punctuation are ignored, so a visible "First name:" matches the name "first name". The criterion does not apply to a control with no visible text label, but such a control still needs an accessible name under 4.1.2.
aria-label with a more "helpful" phrase that leaves out the visible word. The attribute overrides the visible text for assistive technology.Government forms are full of short button labels: Reserve, Look up, Pay, Apply, Renew. When a screen reader or voice user hears or says one thing and the control is named another, the task stalls at the last step. This is also a place where automated tools report a pass (every button has a name), while a person speaking the visible label gets no response. Relevant background: WCAG 2.1 AA and the ADA.
<button aria-label="Book a site">Reserve</button><button>Reserve</button>
<!-- or, with more detail that still starts with the visible word: -->
<button aria-label="Reserve campsite 12">Reserve</button><label for="vr-zip">ZIP code</label>
<input id="vr-zip" aria-label="Postal area" inputmode="numeric"><label for="vr-zip">ZIP code</label>
<input id="vr-zip" inputmode="numeric" autocomplete="postal-code"><a href="/pay" aria-label="Account balance">Pay bill</a><a href="/pay">
Pay bill
<span class="visually-hidden">for account ending 4471</span>
</a>// SwiftUI
Button("Renew book") { renew() }
.accessibilityLabel("Extend loan")// SwiftUI
Button("Renew book") { renew() }
.accessibilityLabel("Renew book, The Grapes of Wrath")// Jetpack Compose
Button(
onClick = { reserve() },
modifier = Modifier.semantics { contentDescription = "Book campsite" }
) { Text("Reserve") }// Jetpack Compose
Button(
onClick = { reserve() },
modifier = Modifier.semantics { contentDescription = "Reserve campsite 12" }
) { Text("Reserve") }If you do not override the name at all, both platforms use the visible text, which is the simplest way to comply.
aria-label and aria-labelledby on elements that also have visible text, and compare the two by eye.aria-label "for clarity".aria-label exist only where they add words after the visible text.