What happens with aria-labelledby, aria-label and aria-describedby
on static HTML elements?
An interesting Twitter thread sprung up from a Tweet about overriding elements with aria-label
with a follow up thread with my colleagues.
I was asked to test the results of aria-label
on static content. This is what is below, along with aria-labelledby
and aria-describedby
, as well as an examination of what is "supposed to happen" according to the Accessible Name computation.
Conclusion: TLDR
Screen readers are all over the map on what they do when an aria-label
, aria-labelledby
, and aria-describedby
on static content
Results
Well supported elements
-
aria-label
,aria-labelledby
andaria-describedby
are robustly supported for interactive content elements such as links and form controls including the manyinput
types. They also work well ondiv
andspan
elements with interactive roles such asrole=link
,button
. By design,aria-label
oraria-labelledby
replace any other label text inside the element. - All three are OK on
nav
andmain
elements. - They are OK on
div
elements IF they haverole=navigation
,search
,main
,img.
- They are OK on a
table
element (except ignored by VoiceOver on iOS). aria-describedby
is OK onh1, h2, h3, h4, h5, h6
elements.
Other static elements with aria-label
, aria-labelledby
and aria-describedby
NOTE: There are no appreciable differences in these tests across popular browsers, platforms or in iframes.
JAWS | NVDA | VoiceOver | Talkback | |
---|---|---|---|---|
aria-labelledby
and aria-label |
Ok on Ignored on all other static content except those listed above |
Ignored on all other static content except those listed above |
Other elements read aria-label with virtual cursor and then let user enter and read the contents. |
All the static content is overridden except |
aria-describedby |
Well supported on static content |
Ignored on static content not listed above unless given an interactive role and |
VO on MacOS is different from iOS VO on MacOS is OK on most static content. VO on iOS only reads it if on |
Well supported on static content |
aria-label
and aria-labelledby
have similar behaviour in screen readers and the Accessibility API, but aria-label
should be reserved for when there is no visible text on the page to reference or when keeping track of id
values would be too difficult.
What happens when roles are added?
- If the role is an interactive
role
(that can be clicked on such as button or link) or an image role thearia-label
oraria-labelledby
overrides the text - If its a heading
role
,aria-label
oraria-labelledby
overrides it on NVDA, VoiceOver and Talkback. JAWS ignores thearia-label
oraria-labelledby
. - If the
role
is a static role thenaria-label
will be ignored by all screen readers except Talkback which overrides the static content (except if itslistitem
role, then its ignored).
What do the Specs say?
The Accessible Name Computation spec provides a calculation of an accessible NAME. the definition says:
The accessible name is the name of a user interface element. ...So I tried to look up "user interface element", in the glossary. There is no definition for "user interface element" in the ARIA spec, the Accessible Name Computation spec or the HTML 5.2. It is clear that different assistive technologies are interpreting this differently. JAWS doesn't override headings with
aria-label
, which NVDA, VO on iOS and MacOS do. So these AT's are interpreting a heading as a user interface element. I filed a bug with the aria spec and will update this article with the results of that discussion.
I filed an issue with the ARIA spec to define the term "user interface elements" (do they include static elements?) with the hope that it will help screen readers manufacturers know what to do.
Static text Element tests with aria-roles with aria-label, aria-labelledby and aria describedby
BEGIN TEST ==========
This is an h1 with aria-label="test 1"
h2 with aria-label="test 2"
h3 with aria-label="test 3"
h4 with aria-label="test 4"
h5 with aria-label="test 5"
h6 with aria-label="test 6"
p element with aria-label="test 8"
span element with aria-label="test 9"- li with aria-label="Test 11". It is inside of a ul element
- li element inside ul element. The ul has aria-label="Test 11"
This is a table with aria-label="test21" on table element | header 2 |
---|---|
td 1 | td 2 |
This is a table with aria-label="test22" on th element | header 2 |
---|---|
td 1 | td 2 |
This is a table with aria-label="test23" on td element | header 2 |
---|---|
td 1 | td 2 |
This is a table with aria-label="test22" on 2nd row tr element | header 2 |
---|---|
td 1 | td 2 |
=== aria-labelledby ===
aria-labelledby="static-text" on an h1 referencing text below
h2 with aria-labelledby="static-text"
h3 with aria-labelledby="static-text"
h4 with aria-labelledby="static-text"
h5 with aria-labelledby="static-text"
h6 with aria-labelledby="static-text"
p element with aria-labelledby="static-text"
span element with aria-labelledby="static-text"- li with aria-labelledby="static-text" . It is inside of a ul element
- li element inside ul element. The ul has aria-labelledby="static-text"
This is a table with aria-labelledby="static-text" on table element | header 2 |
---|---|
td 1 | td 2 |
This is a table with aria-labelledby="static-text" on th element | header 2 |
---|---|
td 1 | td 2 |
This is a table with aria-labelledby="static-text" on td element | header 2 |
---|---|
td 1 | td 2 |
This is a table with aria-labelledby on 2nd row tr element | header 2 |
---|---|
td 1 | td 2 |
aria-describedby="static-text" on an h1 referencing text below
h2 with aria-describedby="static-text"
h3 with aria-describedby="static-text"
h4 with aria-describedby="static-text"
h5 with aria-describedby="static-text"
h6 with aria-describedby="static-text"
p element with aria-describedby="static-text"
span element with aria-describedby="static-text"- li with aria-describedby="static-text" . It is inside of a ul element
- li element inside ul element. The ul has aria-describedby="static-text"
This is a table with aria-describedby="static-text" on table element | header 2 |
---|---|
td 1 | td 2 |
This is a table with aria-describedby="static-text" on th element | header 2 |
---|---|
td 1 | td 2 |
This is a table with aria-describedby="static-text" on td element | header 2 |
---|---|
td 1 | td 2 |
This is a table with aria-describedby on 2nd row tr element | header 2 |
---|---|
td 1 | td 2 |
Static text Elements with role attributes and aria-label, aria-labelledby and aria describedby
BEGIN TEST ======= aria-label ===
span element with aria-label="test 12" with role=img
div element with aria-label="test 35" with role=note
div element with aria-label="test 15" with role=button and tabindex=0
span element with aria-label="test 19" with role=listitem
=== aria-labelledby ===
span element with aria-labelledby="static-text" with role=img
div element with aria-labelledby="static-text" with role=button and tabindex=0
span element with aria-labelledby="static-text" with role=listitem
=== aria-describedby ===
span element with aria-describedby="static-text" with role=img
div element with aria-describedby="static-text" with role=button and tabindex=0
span element with aria-describedby="static-text" with role=listitem
END OF TEST ===============
Results
JAWS | NVDA | VoiceOver | Talkback | |
---|---|---|---|---|
FireFox (Sept 2018) | Aria-label, aria-labelledby are ignored on all static content unless it has a an interactive role, aria-describedby well supported on static content |
Aria-label, aria-labelledby are override headings. On other elements there is no aria-label aria-labelledby read. aria-describedby pooly supported on static content |
N/A | N/A |
IE (Sept 2018) | Aria-label, aria-labelledby are ignored on all static content unless it has a an interactive role, aria-describedby well supported on static content |
Aria-label, aria-labelledby are override headings. On other elements there is no aria-label aria-labelledby read. aria-describedby pooly supported on static content |
N/A | N/A |
Chrome (Sept 2018) | Aria-label, aria-labelledby are ignored on all static content unless it has a an interactive role, aria-describedby well supported on static content |
Aria-label, aria-labelledby are override headings. On other elements there is no aria-label aria-labelledby read. aria-describedby pooly supported on static content |
All the headings are overridden by the VO, User then has to interact with heading to hear it, but would not discover that easily. Other elements read aria-describedby pooly supported on static content |
All the static content is overridden except list items which are ignored (weird) aria-describedby well supported on static content |
Safari MacOS (Sept 2018) |
N/A | N/A | All the headings are overridden by the VO, User then has to interact with heading to hear it, but would not discover that easily. Other elements read aria-describedby pooly supported on static content |
N/A |
Safari iOS (Sept 2018) |
N/A | N/A | All the headings are overridden by the VO. aria-describedby pooly supported on static content |
N/A |
Feel free to comment on Twitter @davidmacd
Author information:
David MacDonald is a veteran WCAG member, co-editor of Using WAI ARIA in HTML5 and HTML5 Accessibility Task Force Member. Opinions are my own.
CONTACT US
For a quote or just to chat about your organization's needs
PHONE