Web Accessibility Training
Toronto, Montreal, Ottawa and worldwide via Webex More

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 and aria-describedby are robustly supported for interactive content elements such as links and form controls including the many input types. They also work well on div and span elements with interactive roles such as role=linkbutton. By design, aria-label or aria-labelledby replace any other label text inside the element.
  • All three are OK on nav and main elements.
  • They are OK on div elements IF they have role=navigation, search, main, img.
  • They are OK on a table element (except ignored by VoiceOver on iOS).
  • aria-describedby is OK on h1, 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 td, th

Ignored on all other static content except those listed above

h1, h2, h3, h4, h5, h6 are overridden. So are elements with role=heading.

landmark roles OK.

Ignored on all other static content except those listed above

h1, h2, h3, h4, h5, h6 are overridden. So are elements with role=heading. User can interact with heading to hear it, but its not easily discoverable.

landmark roles OK.

Other elements read aria-label with virtual cursor and then let user enter and read the contents.

All the static content is overridden except ul and li which are ignored

aria-describedby

Well supported on static content

h1, h2, h3, h4, h5, h6 are OK as are elements with role=heading.

Ignored on static content not listed above unless given an interactive role and tabindex=0, and then only if the users tabs to it (not arrows to it).

VO on MacOS is different from iOS

VO on MacOS is OK on most static content.

VO on iOS only reads it if on landmark roles.

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 the aria-label or aria-labelledby overrides the text
  • If its a heading role , aria-label or aria-labelledby overrides it on NVDA, VoiceOver and Talkback. JAWS ignores the aria-label or aria-labelledby.
  • If the role is a static role then aria-label will be ignored by all screen readers except Talkback which overrides the static content (except if its listitem 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"
div element with aria-label="test 10"
legend element with aria-label="Test 11". It is inside a fieldset element
  • 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"
footer element with aria-label="test 20"

header element with aria-label="test 20"

main element with aria-label="test 20"

section element with aria-label="test 20

This is a table with aria-label="test21" on table elementheader 2
td 1td 2

This is a table with aria-label="test22" on th elementheader 2
td 1td 2

This is a table with aria-label="test23" on td elementheader 2
td 1td 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"
div element with aria-labelledby="static-text
legend element with aria-labelledby="static-text" . It is inside a fieldset element
  • 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"
footer element with aria-labelledby="static-text"

header element with aria-labelledby="static-text"
main element with aria-labelledby="static-text"


section element with aria-labelledby="static-text"

This is a table with aria-labelledby="static-text" on table elementheader 2
td 1td 2

This is a table with aria-labelledby="static-text" on th elementheader 2
td 1td 2

This is a table with aria-labelledby="static-text" on td elementheader 2
td 1td 2
=== aria-describedby ===

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"
div element with aria-describedby="static-text"
legend element with aria-describedby="static-text" . It is inside a fieldset element
  • 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"
footer element with aria-describedby="static-text"

header element with aria-describedby="static-text"
main element with aria-describedby="static-text"

section element with aria-labelledby="static-text"

This is a table with aria-describedby="static-text" on table elementheader 2
td 1td 2

This is a table with aria-describedby="static-text" on th elementheader 2
td 1td 2

This is a table with aria-describedby="static-text" on td elementheader 2
td 1td 2

End TEST ==========

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 13" with role=img
span element with aria-label="test 14" with role=button and tabindex=0

div element with aria-label="test 15" with role=button and tabindex=0

span element with aria-label="test 16" with role=heading and aria-level=1
div element with aria-label="test 17" with role=heading and aria-level=1
span element with aria-label="test 18" with role=link
span element with aria-label="test 19" with role=listitem
div element with aria-label="test 20" with role=banner
div element with aria-label="test 20" with role=contentinfo
div element with aria-label="test 20" with role=complementary
div element with aria-label="test 20" with role=main
div element with aria-label="test 20" with role=search
div element with aria-label="test 20" with role=banner
div element with aria-label="test 20" with role=navigation

=== aria-labelledby ===

span element with aria-labelledby="static-text" with role=img
div element with aria-labelledby="static-text" with role=img
span element with aria-labelledby="static-text" with role=button and tabindex=0

div element with aria-labelledby="static-text" with role=button and tabindex=0

span element with aria-labelledby="static-text" with role=heading and aria-level=1
div element with aria-labelledby="static-text" with role=heading and aria-level=1
span element with aria-labelledby="static-text" with role=link
span element with aria-labelledby="static-text" with role=listitem
div element with aria-labelledby="static-text" with role=banner
div element with aria-labelledby="static-text" with role=contentinfo
div element with aria-labelledby="static-text" with role=complementary
div element with aria-labelledby="static-text" with role=main
div element with aria-labelledby="static-text" with role=search
div element with aria-labelledby="static-text" with role=banner
div element with aria-labelledby="static-text" with role=navigation

=== aria-describedby ===
span element with aria-describedby="static-text" with role=img
div element with aria-describedby="static-text" with role=img
span element with aria-describedby="static-text" with role=button and tabindex=0

div element with aria-describedby="static-text" with role=button and tabindex=0

span element with aria-describedby="static-text" with role=heading and aria-level=1
div element with aria-describedby="static-text" with role=heading and aria-level=1
span element with aria-describedby="static-text" with role=link
span element with aria-describedby="static-text" with role=listitem
div element with aria-describedby="static-text" with role=banner
div element with aria-describedby="static-text" with role=contentinfo
div element with aria-describedby="static-text" with role=complementary
div element with aria-describedby="static-text" with role=main
div element with aria-describedby="static-text" with role=search
div element with aria-describedby="static-text" with role=banner
div element with aria-describedby="static-text" with role=navigation
Here is some text to reference with id="static-text"

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, img role, or nav, main, search roles.

aria-describedby well supported on static content

Aria-label, aria-labelledby are override headings.

landmark roles OK.

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, img role, or nav, main, search roles.

aria-describedby well supported on static content

Aria-label, aria-labelledby are override headings.

landmark roles OK.

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, img role, or nav, main, search roles.

aria-describedby well supported on static content

Aria-label, aria-labelledby are override headings.

landmark roles OK.

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-label when virtual cursor hits the elements and then let user enter and read the contents.

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-label when virtual cursor hits the elements and then let user enter and read the contents.

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. nav reads the label and then the contents correctly. On other elements there is no aria-label read.

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


EMAIL

help at can hyphen adapt dot com, (spoken phonetically to trick spam bots)

PHONE

six one three, eight zero six, nine zero zero five

SOCIAL MEDIA