Never Let aria-label Contradict Visible Text
NEVER: Give a control an `aria-label` that contradicts or omits its visible text — on any role that names from child content, `aria-label` REPLACES that text, so `<button aria-label="Submit form">Save</button>` answers only to "Submit form" and a voice-control user saying "click Save" hits nothing (WCAG SC 2.5.3 Label in Name, Level A requires the accessible name to contain the visible string). Name from child content; use `aria-labelledby` to point at visible text elsewhere; reserve `aria-label` for controls with no visible text. Extending is fine — `aria-label="Save draft"` on a button reading "Save".
Take the accessible name from the visible text; if both exist, the name must contain the visible string
Bad
Good
Why it matters
This is the mismatch case, and it is distinct from every neighbouring rule in the corpus. content-dont-ship-schema and content-icons-have-labels (and interactions-rams-aria-labels) cover the inverse problem: an icon-only control with no visible text, where aria-label is exactly right. Here the control already has text. On a button, div, link, or any role that supports naming from child content, aria-label does not add to that text — it replaces it, hiding the child content from assistive technology.
So <button aria-label="Submit form">Save</button> is a button that reads "Save" and answers to "Submit form". A voice-control user who says "click Save" hits nothing, which is why WCAG SC 2.5.3 Label in Name (Level A) requires the accessible name to contain the visible label text. Prefer naming from child content; when you need to reference text elsewhere, use aria-labelledby pointing at the visible element.
Reserve aria-label for controls with no visible text at all, and if you must extend a name, keep the visible string inside it (aria-label="Save draft" on a button reading "Save" is fine).