Reviewing the accessibility of web solutions, I've noticed that missing accessible name is a common issue. It often appears in buttons and links that do not have visible labels and have icons/images as content. It makes elements not visible to all users and for certain assistive technologies (ATs). Adding an accessible name is an easy and quick fix, but we have to follow some rules to make it valid.
What are naming techniques and how to use them? What is the difference between
aria-labelledby? What are common developers' mistakes and how to avoid them? I try to cover all of this to help you write more accessible code.
Accessible name—the basics
An accessible name makes an element visible and understandable for all users, also for those who use assistive technologies. It improves the semantics and often the structure of the website, user agents use it to create accessibility trees, and it's valuable information for indexer robots, so it impacts SEO. Missing an accessible name can completely block users' interaction.
We have several naming techniques that we can use:
- Child content (static text content, alt attribute for image…)
- native markup elements, ex.:
When an accessible name is not implemented using native markup (HTML content) or one of the primary techniques (e.g., the
aria-labelledby attributes), browsers calculate an accessible name from other attributes as a fallback mechanism. Because the attributes used for this calculation are not intended for naming, a name itself it's usually of low quality and ineffective.
Which elements required a name?
According to WCAG (Web Content Accessibility Guideline), all focusable, interactive elements, dialogs, and some structural containers should have an accessible name. Many other elements can be named, but whether a name will enhance the accessible experience depends on context.
Important! Name for generic role elements, like div and span is not allowed. It's also prohibited in a paragraph.
If you need to add a name to the container, you need to set a specific role for it.
Here you can find a list of ARIA roles with information if a name is required, recommended, or not allowed: Naming role guidance table
Certain elements get their name from the content, for example: buttons, links, and headings. The best way is to use a visible name that is coherent for all users and AT (Assistive Technologies).
The full list of elements that get a name from their content you can find here: Naming with child content
Native markup elements
The best practice is to use native markup to name HTML elements:
- From fields - use
labelfor form fields:
aria-label attribute allows adding a name to an element that is not visually rendered. A value of the attribute is a name in the form of a string.
It works in 2 different ways, depending on the role of the element:
1. If you add it on an element that supports naming from children's content, it overrides the content and hides it from ATs, for example:
2. If added on any other element (on which is allowed), both,
aria-label value and element content are rendered, for example:
aria-labelledby attribute, similar to
aria-label, allows adding a name for an element but instead of typing a name in an attribute value directly, uses another element and binds it with its id. With this attribute, you can reference hidden elements too, for example:
aria-labelledby, you can reference multiple elements to use their content as a name. You can also reference the element itself. Content will be concatenated, for example:
In the above example, the name will be: "Download ebook PDF, 2.4 MB" (yes, with space before "PDF, 2.4 MB"!)
aria-labelledby used on the element which supports naming from child content (ex. button, links), it overrides the content of an element and hides it from ATs.
When you use
aria-labelledby on a button or link with visible text, the name value should match the visible text or at least start with visible text (it's required by WCAG SC 2.5.3). It is required for using speech-recognition technology - speech input users rely on visual labels when using voice commands.
If you reference an element in the
aria-labelledby attribute's value more than once during a name calculation, the second and any subsequent references will be ignored.
aria-labelledby attribute cannot be chained, you should reference an element with content, not with another
Visually hidden text
Instead of using additional attributes, you can add visually hidden text which is rendered for ATs. This popular technique is easy to implement and works easily with Tailwind class
sr-only. Using it you can add an accessible name but only in elements that support naming from child content (ex.
link) or an additional description.
If you don't use Tailwind, you can use the following CSS code:
Example as an accessible name:
Example as a description:
Don't do it! Common developers' mistakes
- Don't overuse aria properties for adding names. Remember not every element needs
aria-label. When possible, use a native HTML solution, not ARIA.
- Don't use
paragraph.Check if ARIA name property is allowed on a specific element. You can use automatic tools in the browser—axe devtools, lighthouse, or check accessibility in devtools.
- If you overwrite an element's content using ARIA property, test it.
Tips to write clear accessible names
- Use names for functions or purposes, not forms. For example, if a close button has an X icon, use "Close" text not "X".
- Put the most important words first, if an element enables an action, use a verb at the beginning.
- Use short and clear names (for most cases, 3-4 words should be sufficient).
- Do not include roles and element's name inside a name value (like "button", "image" or "navigation"), this role will be announced with AT
- Start a name with a capital letter, it helps some AT to announce it properly
aria-describedbyfor additional description. It works similarly to
aria-labelledby. It allows adding a description to an element by binding another element by its
id. You can also reference a hidden element.
Some specific cases
Multiple elements with the same action—ex. in the product list
Often on a category page, in the product listing, you have the same actions, with the same label (or icon) or different products.
Why is it an issue?
When AT user reviews a page using buttons or links, he sees multiple "Add to cart" links
You can use
aria-label with the product name after the action name or visually hidden text inside the action link/button:
You can also use
aria-labelledby but you need to use unique ids which can provide additional complication in code, so I don't recommend this approach.
Image inside a
button or a link—does an
alt attribute work as an accessible name?
Yes, if you use an image as a content of a link or a button, you can use its
alt attribute to set an accessible name, for example:
You can also hide an image inside and use
aria-label or hidden text, for example:
I recommend using
aria-label or hidden text solution, for the following reasons:
- Some automatic tests detect a link with an image and without an additional name as an error. In this case, you can avoid additional discussion with a client, while he runs an external accessibility scanner
- You and other devs that maintain code need to remember to adjust image alt to link destination, not to image representation, even if it's evident to you, it doesn't have to be clear for junior dev or content manager, a name added for a link is easier to maintain in this case
Any HTML element can have a title attribute specified. It is presented visually as a tooltip when the user hovers over the element with a pointing device, which is not particularly discoverable and is also not accessible to visual users without a pointing device. It can be used as the element's fallback accessible name but remember that some ATs or devices agent can omit it. It is recommended to use the explicit labelling techniques described above.
What about an additional description—
aria-describedby property works similarly to the
aria-labelledby - it allows adding a description to an element by binding another element by its id. It also allows referencing hidden elements.
Screen readers present descriptions last, sometimes after a slight delay. Some screen readers do not announce descriptions by default but instead, inform users of their presence so that users can press a key that will announce the description.
How to test an accessibility name?
You can easily check your accessibility name during development. You can use tools directly in your browser:
1. Make a quick scan using an automatic test. It allows you to find where the accessible name is missing and if applied aria roles are allowed on the specific element.
Axe DevTools example:
Accessibility checker example:
2. You can review the accessibility tree generated from your code and check the accessibility properties of the element in DevTools:
Check how to use the accessibility pane in DevTools in this guide.