This article covers:
- What is
aria-labelledby? - When to use
aria-labelledby - How does
aria-labelledbywork? - What is the order of precedence?
- Can the name come from anywhere in the DOM?
- Can it use more than one source?
- Can it reference the element itself?
- What happens with empty strings?
- What happens with broken references?
- Can it cross shadow DOM boundaries?
- Can it reference hidden elements?
- Which roles and elements can it be applied to?
- Punctuation and announcement
- Conclusion
What is aria-labelledby?
The aria-labelledby attribute lets you use existing text on the page to name another element for assistive technologies.
Under the hood, it works by referencing one or more elements whose text is used to compute the element’s accessible name.
In the following example, the <nav> element has an accessible name of “About us”, taken from the text content of the referenced heading:
<nav aria-labelledby="aaa">
<h4 id="aaa">About us</h4>
</nav>
When to use aria-labelledby
The aria-labelledby attribute can be used to provide or override the accessible name of an element.
It is commonly used:
- when an element does not have a native way to generate an accessible name
- when visible text elsewhere in the document should be used as the name
- when you need to override an element’s existing accessible name
When visible content already exists in the page, aria-labelledby should generally be used in preference to aria-label, as it reuses text that is available to all users.
How does aria-labelledby work?
aria-labelledby creates an explicit, ID-based relationship.
When present, the browser:
- reads the value of aria-labelledby
- resolves each
IDto a DOM node - extracts the text content from those nodes
- uses the combined text as the element’s accessible name
What is the order of precedence?
The aria-labelledby attribute is the most powerful author-provided method of assigning an accessible name to an element.
In simplified order:
- If present, use
aria-labelledby. - Otherwise, if present, use
aria-label. - Otherwise, use the element’s native HTML naming mechanism, where applicable, including:
- Visible text content
- A
<label>associated with a form control - The
altattribute on images - A
<legend>for a<fieldset> - A
<caption>for a table - A
<figcaption>for a<figure>
Importantly, just because these two ARIA attributes take precedence in name computation, this does not mean they should be used.
Where possible, always use the element’s native HTML naming mechanism, as this is typically more robust, more predictable, and better supported across browsers and assistive technologies.
Can the name come from anywhere in the DOM?
The referenced element must exist in the same document and have a valid, unique id.
In the following example, the button has an accessible name of “Buy Lawn Mower”, taken from a paragraph elsewhere in the document:
<button aria-labelledby="bbb">Buy</button>
...
<p id="bbb">Buy Lawn Mower</p>
Can it use more than one source?
More than one element can be referenced using space-separated values in the aria-labelledby attribute.
In the following example, the button has an accessible name of “Buy Lawn Mower On special”.
This name was created by concatenating the text from elements ccc (“Buy Lawn Mower”) and ddd (“On special”).
The accessible name is compiled based on the order they are listed in the aria-labelledby attribute.
The order in which those elements appear in the DOM is irrelevant.
<button aria-labelledby="ccc ddd">Buy</button>
<p id="ccc">Buy Lawn Mower</p>
<p id="ddd">On special</p>
Can it reference the element itself?
An element may include its own id as part of the aria-labelledby reference.
In the following example, the button’s accessible name is “Buy Lawn Mower On special”, created from:
- its own text content -
eee(“Buy”). - the referenced elements
fff(“Lawn Mower”) andggg(“On special”).
<button id="eee" aria-labelledby="eee fff ggg">Buy</button>
<p id="fff">Lawn Mower</p>
<p id="ggg">On special</p>
The accessible name computation algorithm prevents infinite loops and ensures the element’s own content is only included once.
What happens with empty strings?
If all referenced elements resolve to empty text strings, the resulting accessible name will be empty.
In the following example, the button is attempting to reference another element with no content:
<button aria-labelledby="hhh">Buy</button>
<p id="hhh"></p>
In practice, some browsers (including Chrome) may fall back to the element’s own text content if the aria-labelledby reference resolves to an empty string. So, the name would be “Buy”.
This fallback should not be relied upon. If the element has no internal text content, the accessible name will be empty.
In the following example, there is no fallback naming mechanism, resulting in a control with no accessible name.
<button aria-labelledby="iii"></button>
<p id="iii"></p>
What happens with broken references?
The accessible name may be empty or incomplete if a referenced id:
- does not exist
- is duplicated
- is added or removed dynamically
Broken aria-labelledby references fail silently, making these issues easy to miss during development.
When debugging, inspect the element in the accessibility tree to confirm that its accessible name is being computed as expected, rather than relying solely on markup inspection.
Can it cross shadow DOM boundaries?
The aria-labelledby attribute cannot cross shadow DOM boundaries.
The following examples are illustrative. The #shadow-root line represents the shadow DOM boundary and is not literal HTML.
An element in the light DOM cannot reference an element inside a shadow root using aria-labelledby. Any such reference is treated as if the id does not exist.
<button aria-labelledby="jjj">Buy</button>
<greeting-widget>
#shadow-root
<p id="jjj">Buy lawn mowers</p>
</greeting-widget>
Similarly, elements inside a shadow root cannot reference elements outside that shadow root.
<p id="kkk">Buy lawn mowers</p>
<greeting-widget>
#shadow-root
<button aria-labelledby="kkk">Buy</button>
</greeting-widget>
In both cases, the result is a silent failure, and the referenced text will not contribute to the accessible name.
Can it reference hidden elements?
aria-labelledby can reference hidden content.
In the following example, the text string is hidden using aria-hidden="true" but the button will still have an accessible name of “ARIA-hidden”:
<p id="lll" aria-hidden="true">ARIA-hidden</p>
<button aria-labelledby="lll">
Buy
</button>
In the following example, the text string is hidden using the hidden attribute but the button will still have an accessible name of “Hidden attribute”:
<p id="mmm" hidden>Hidden attribute</p>
<button aria-labelledby="mmm">
Buy
</button>
In the following example, the text string is hidden using style="display:none" but the button will still have an accessible name of “Display-none”:
<p id="nnn" style="display:none">Display-none</p>
<button aria-labelledby="nnn">
Buy
</button>
In the following example, the text string is hidden using style="visibility:hidden" but the button will still have an accessible name of “Visibility-hidden”:
<p id="ooo" style="visibility:hidden">Visibility-hidden</p>
<button aria-labelledby="ooo">
Buy
</button>
In the following example, the text string is hidden using a CSS class but the button will still have an accessible name of “Visually-hidden”:
<p id="ppp" class="visually-hidden">Visually-hidden</p>
<button aria-labelledby="ppp">
Buy
</button>
In the following example, the text string is hidden using style="opacity:0" but the button will still have an accessible name of “Opacity-invisible”:
<p id="qqq" style="opacity:0">Opacity-invisible</p>
<button aria-labelledby="qqq">
Buy
</button>
More information on hidden content and how it relates to aria-labelledby and aria-describedby.
Which roles and elements can it be applied to?
The aria-labelledby attribute is a global ARIA attribute which means it is allowed on all HTML elements.
However,
code>aria-labelledby is intended for elements whose roles support author-provided accessible names. These roles can be either implicit (native to the HTML element) or explicit (assigned via ARIA).
Most roles support author-provided accessible names, but some roles are not intended to be named by authors, including:
codedefinitiondeletionemphasisinsertionmarkparagraphpresentationnonestrongsubscriptsuperscriptsuggestionterm
While aria-labelledby is valid markup on any element, applying it to elements or roles that do not support accessible naming will have no practical effect.
Punctuation and announcement
In some of the examples above, the computed accessible name is formed by concatenating text from multiple sources.
This concatenation process does not insert punctuation or pauses. The referenced text strings are merged into a single text string exactly as provided.
As a result, screen readers may not pause naturally between concatenated segments, which can affect how the name is announced.
Conclusion
The aria-labelledby attribute is a powerful tool for generating accessible names from existing content.
However, it should be used with care, and not as a first resort. Where possible, rely on native HTML naming mechanisms.