Categories
HTML Accessibility

aria-labelledby usage notes

Dave wearing a funny hat

updated August 21st 2023

Like aria-label, aria-labelledby provides the opportunity for a developer to expose a short text string as the accessible name for an element. The mechanism to do so differs. While aria-label accepts a string of text, aria-labelledby accepts 1 or more id values (NOT a STRING OF TEXT).

The same opportunity is afforded by native HTML labelling features, please do use the native features wherever practical!, for example:

  • <label for="pithy">poot</label> <input type="text" id="pithy">
  • <img alt="creamy pie">
  • <button>belt on</button>

aria-labelledby is one of a number of secondary methods to label native HTML UI elements. It works particularly well on interactive elements, it also works well on most block level elements old skool term that have explicitly or implicitly defined structural roles. It works less well or not at all on text level semantics. It is prohibited as are any form of accessible name on a whole slew of roles.

Implicit roles are those applied automatically by browsers to native HTML elements.

Explicit roles are those applied by developers using the role attribute. When applied they override the implicit role of an element.

(Somewhat out of place here) general rules for labeling

  1. Prefer visible over hidden labels
    1. Prefer text labels over icons
    2. If icons are used provide a supplementary text label ( may be displayed on focus/hover)
  2. Place visible labels as expected:
    1. For a checkbox or radio button, place the label immediately after the field.
    2. If not a checkbox or radio button, place the label immediately before the field.
  3. Prefer native HTML labeling mechanisms, for Native HTML controls, over ARIA labeling mechanisms.

Never be tempted to use placeholder text as a label. It SUX.

Questions on aria-labelledby usage

I find myself regularly asking the these questions in regards to aria-label:

  1. Is it a good idea to use aria-labelledby on element X?
  2. Does aria-labelledby work as expected i.e is announced by screen readers on element Z?
  3. Is aria-labelledby allowed on element Y?

FYI empty aria-labelledby="" does not equal empty alt="", the latter signals that an img element has no useful information, the former does nothing.

aria-labelledby masks any other accessible name source.

aria-labelledby referencing content

hidden content

It’s legit for aria-labelledby to reference a hidden element, it makes no difference to the resulting accessible name if the content is hidden (using CSS display:none, for example) Refer to Hiding Content Has No Effect on Accessible Name or Description Calculation

<a href="beefy.html" aria-labelledby="unseen">
now you don't</a>

<p id="unseen" hidden>Now you hear me</p>

accessible name: "Now you hear me"

self and multiple references

You can include text that would be exposed as the accessible name if aria-labelledby wasn’t there by adding an id to the element with the aria-labelledby and referencing the value, you can also reference multiple elements:

<a href="noise.html" id="heard" 
aria-labelledby="unseen heard">
now you do</a>

<p id="unseen" hidden>Now you hear me,</p>

accessible name: "Now you hear me, now you do"

The order in which you reference the id values effects the string concatenation order:

<a href="alphabet.html" id="pre" 
aria-labelledby="pre a b c">Easy as</a>

accessible name: "Easy as A B C"

<a href="alphabet.html" id="pre" 
aria-labelledby="pre c b a">Easy as</a>

accessible name: "Easy as C B A"

<span id="a">A</span> 
<span id="b">B</span>
<span id="c">C</span>

Spaces between strings are added by the browser

Today I learned that concatenated text does now have spaces by default, mea culpa.

Append the result of each step above, with a space, to the total accumulated text.

source: https://w3c.github.io/accname/#computation-steps

Be aware that concatenated text does not have spaces by default, so you will need to include spaces.

<a href="alphabet.html" id="pre2" 
aria-labelledby="pre2 a b c">Easy as</a>

accessible name: "Easy asABC"

<a href="alphabet.html" id="pre2" 
aria-labelledby="pre2 a b c">Easy as </a>

accessible name: "Easy as ABC"

<span id="a">A</span> 
<span id="b">B</span>
<span id="c">C</span>

Try it yourself – Codepen aria-labelledby examples

See the Pen
aria-labelledby examples
by steve faulkner (@stevef)
on CodePen.

 

humble guidance

For HTML elements I have provided some guidance on aria-labelledby usage (which by all means you may disagree with):

 

Could I use aria-labelledby?
HTML element aria-labelledby notes
a with href yes Masks text content, so only aria-labelledby is announced:

<a href="home.html" aria-labelledby="neon">uncle meat</a>

<p id="neon">some text</p>

Be wary of label in name issues

a without href no a without href is not a link and not exposed as a link. Maps to role=generic naming not allowed
abbr no title attribute works but announcement is a user preference in some screen readers (off by default). Refer to Short note: The abbreviation appreciation society
address no Does not mask content: accessible name provided via aria-labelledby should generally be announced when the address is navigated to.

aria-labelledby use not well supported as yet

area with href no use alt
area without href no a without href is not a link and not exposed as a link. Maps to role=generic naming not allowed
article yes Does not mask content: accessible name provided via aria-labelledby will generally be announced when the article is navigated to.
aside yes Does not mask content. Accessible name provided via aria-labelledby will generally be announced when the aside is navigated to.
audio yes Prefer visible, a heading perhaps (via aria-labelledby if you like)
b no Maps to role=generic naming not allowed
base no not UI
bdi no Maps to role=generic naming not allowed
bdo no Maps to role=generic naming not allowed
blockquote no aria-labelledby use not well supported
body no aria-labelledby use not supported
br no Maps to role=generic naming not allowed
button yes masks text content, so only aria-labelledby is announced:

<button aria-labelledby="neon">Herbert</button>

<p id="neon">Patrick H. Lauke</p>

Be wary of label in name issues

canvas no Use child content

<canvas><p><a href="https://www.youtube.com/watch?v=y8b7f0ivzUo">Pictures of Lily</a></p></canvas>

caption no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
cite no Maps to role=generic naming not allowed
code no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
col no not UI
colgroup no not UI
data no Maps to role=generic naming not allowed
datalist no For aria-labelledby on <datalist> element itself.
dd no aria-labelledby use not well supported
del no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
dfn no aria-labelledby use not well supported
details yes Does not mask content: When details has an accessible name it is announced as a group along with its accessible name (test case).
dialog yes Does not mask content: accessible name provided via aria-labelledby will generally be announced when the dialog is navigated to.
div no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
dl yes Fairly good support across browsers/screenreaders.
dt no aria-labelledby use not well supported
em no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
embed no aria-labelledby use not well supported
fieldset yes aria-labelledby overrides accessible name from legend content (if present). Otherwise, does not mask content: accessible name provided via aria-labelledby will generally be announced when the fieldset is navigated to.
figcaption no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
figure yes aria-labelledby overrides accessible name from figcaption content (if present). Otherwise, does not mask content: accessible name provided via aria-labelledby will generally be announced when the figure is navigated to.
form yes Does not mask content: accessible name provided via aria-labelledby will generally be announced when the form is navigated to.
form-associated custom element yes Unless the custom element is an extension of a native HTML interactive element, ARIA labeling (aria-label, aria-labelledby) is the primary method of labeling.
h1 to h6 no aria-labelledby use not well supported, works with NVDA/VoiceOver not with JAWS

Masks text content, so only aria-labelledby is announced:

<h1 aria-labelledby="pang">PONG</h1>

<p id="pang">PING</p>

head no not UI
header yes Does not mask content: accessible name provided via aria-labelledby will generally be announced when the header is navigated to.
hgroup no Does not mask content: accessible name provided via aria-labelledby will generally be announced when the hgroup is navigated to.

aria-labelledby use not well supported as yet.

hr yes Will generally be announced when the hr is navigated to.
html no not UI
i no Maps to role=generic naming not allowed
iframe yes Use title attribute for accessible name
img with alt="some text" no Use alt attribute for accessible name
img with alt="" no use alt
img without alt attribute no if you want to add an accessible name to an <img> use alt attribute for accessible name
input type=button yes accessible name from value preferred
input type=checkbox yes accessible name from label preferred
input type=color yes accessible name from label preferred
input type=date yes accessible name from label preferred
input type=datetime-local yes accessible name from label preferred
input type=email yes accessible name from label preferred
input type=file yes accessible name from label preferred
input type=hidden no not UI
input type=image no if you want to add an accessible name to an <input type=image> use alt
input type=month yes accessible name from label preferred
input type=number yes accessible name from label preferred
input type=password yes accessible name from label preferred
input type=radio yes accessible name from label preferred
input type=range yes accessible name from value preferred
input type=reset yes accessible name from value preferred
input type=submit yes accessible name from value preferred
input type=tel yes accessible name from label preferred
input type=text yes accessible name from label preferred
input type=time yes accessible name from label preferred
input type=url yes accessible name from label preferred
input type=week yes accessible name from label preferred
ins no Maps to role=generic naming not allowed
kbd no Maps to role=generic naming not allowed
label no Maps to role=generic naming not allowed (until ARIA 1.3)
legend no aria-labelledby use not well supported
li no aria-labelledby use not well supported
main yes Does not mask content: accessible name provided via aria-labelledby will generally be announced when the main is navigated to.
map no not UI
math no The math element is not currently supported in modern browsers.
mark no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
menu no This element sucks in general, suggest not using.
meta no not UI
meter yes accessible name from label preferred
nav yes Does not mask content: accessible name provided via aria-labelledby will generally be announced when the nav is navigated to.
noscript no not UI
object no aria-labelledby use not well supported
ol yes Fairly good support across browsers/screenreaders.
optgroup no Use label attribute
option no Use text content of option or use a label attribute.
output no aria-labelledby use not supported
p no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
param no not UI
picture no not UI
pre no Maps to role=generic naming not allowed
progress yes accessible name from label preferred or a heading perhaps (via aria-labelledby if you like).
q no Maps to role=generic naming not allowed
rp no Maps to role=generic naming not allowed
rt no Maps to role=generic naming not allowed
ruby no Maps to role=generic naming not allowed
s no Maps to role=generic naming not allowed
samp no Maps to role=generic naming not allowed
script no not UI
section yes Does not mask content: accessible name provided via aria-labelledby will generally be announced when the section is navigated to.
select yes accessible name from label preferred
slot no not UI
small no Maps to role=generic naming not allowed
source no not UI
span no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
strong no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
style no not UI
SVG yes alt="some text" DOES NOT WORK even if the SVG (or any other element) has a role="img"
sub no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
summary no aria-labelledby use not well supported
sup no refer to Roles which cannot be named (Name prohibited) ARIA 1.2
table yes Prefer visible caption element text
tbody no aria-labelledby use not well supported
template no not UI
textarea yes accessible name from label preferred
tfoot no aria-labelledby use not well supported
thead no aria-labelledby use not well supported
time no Maps to role=generic naming not allowed
title no aria-labelledby use not supported
td no aria-labelledby use not well supported
th no aria-labelledby use not well supported
tr no aria-labelledby use not well supported
track no not UI
u no Maps to role=generic naming not allowed
ul yes Fairly good support across browsers/screenreaders.
var no Maps to role=generic naming not allowed
video yes Prefer visible, a heading perhaps (via aria-labelledby if you like)
wbr no Maps to role=generic naming not allowed

Further reading

5 replies on “aria-labelledby usage notes”

I find myself regularly asking the these questions in regards to aria-label: <- should that be aria-labelledby?

Should second column in Humble guidance table also be aria-labelledby?

Leave a Reply

Your email address will not be published. Required fields are marked *