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-label
and 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…)
aria-label
attributearia-labelledby
attribute- native markup elements, ex.:
label
,caption
,figcaption
...
When an accessible name is not implemented using native markup (HTML content) or one of the primary techniques (e.g., the aria-label
or 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
Naming techniques
Child content
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
label
for form fields:input
,textarea
,select
- Use
legend
forfieldset
element - Use
caption
fortable
- Use
figcaption
forfigure
aria-label
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
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:
With 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"!)
both aria-label
and 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-label
or 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.
The aria-labelledby
attribute cannot be chained, you should reference an element with content, not with another aria-labelledby
attribute.
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. button
or 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
aria-label
ondiv
,span
andparagraph.
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
- Use
aria-describedby
for additional description. It works similarly toaria-labelledby
. It allows adding a description to an element by binding another element by itsid
. 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
Solution?
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-labe
l 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
Title
attribute
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
?
The 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.
Use browser extension—Axe DevTools or IBM Accessibility Checker to detect issues.
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.
More resources: