The aria-label
property is made available to us by the Accessible Rich Internet Applications (ARIA) standard. It allows a property/value declaration in HTML as a way of providing an accessible name for an interactive element.
Accessible names
Accessible names use text to identify interactive elements on a page. They allow someone using assistive technology to understand, and then take action on those interactive elements.
Keeping accessible names concise and descriptive is one of the most important things when coding things in an accessible way. A great example of an accessible name is the content placed between opening and closing a
tags:
<a href="duck-breeds.html">
Duck breeds
</a>
Accessible names are computed via an algorithmic process derived from Accessible Name and Description Computation. Here, an algorithm evaluates each DOM node’s text content, attribute content, and associated elements to determine which declaration is the most relevant. This information is then exposed to the browser’s Accessibility Tree.
Assistive technology consumes information generated by the accessibility tree. This in turn enables people using the assistive technology to understand the makeup of a website or web app’s content and take action on it.
Code smell
The term “code smell” refers to small, repeated patterns or one-off, atypical code constructs that indicate something is worth paying attention to. To quote Martin Fowler:
“…smells don't always indicate a problem. […] You have to look deeper to see if there is an underlying problem there—smells aren't inherently bad on their own—they are often an indicator of a problem rather than the problem themselves.”
In my experience, the term code smell usually has a negative connotation when someone mentions it.
It’s a lot like a noticeable smell emanating from the office refrigerator. Ideally it’s some delicious homemade kimchi someone brought in, but more often than not it’s something like some forgotten fish sticks rotting in the back.
To stretch this metaphor to its breaking point, I also don’t think the forgotten food is the result of malice. The person who left the fish sticks might:
- Not be aware of the unwritten rules about bringing fish to the office,
- Have forgotten they placed them there,
- Have been reassigned to a different office and didn’t get a chance to remove them,
- Be getting continuously distracted by other responsibilities,
- etc.
aria-label
as a code smell
Sadly, I run into aria-label
declarations a lot more than I’d expect to. There are probably a whole host of reasons for this, but if I could name some of the more popular factors they may be:
- Unfamiliarity with ARIA leading to using code written by other developers unfamiliar with ARIA,
- Trying to work within the conventions imposed by a lot of contemporary development frameworks,
- Working with limitations of immature component architecture, or
- Wanting to type less into their code editor.
When I encounter too much, or mis-applied aria-label
it makes me take notice. This code smell puts me on alert to investigate things more thoroughly, as it most likely indicates accessibility issues.
Before you scoff at this, I’d encourage you to read the WebAIM Million report. This evaluation of the accessibility of the top 1,000,000 homepages revealed:
“Increased ARIA usage on pages correlated to higher detected errors. The more ARIA attributes that were present, the more detected accessibility errors could be expected.”
That’s a big ol’ oof right there.
ARIA has varying levels of support
Web developers are used to thinking of support as a binary yes or no. However, ARIA is a bit unique in that it’s support is more conditional, and what it actually does is highly contingent on:
- How it is being used, and
- The surrounding context of the rest of the overall experience.
Determining actual ARIA support is a bit more complicated than other web technologies, in that it relies on the:
- Operating system being used,
- Operating system’s version,
- Browser being used,
- Browser’s version,
- Assistive technology being used,
- Assistive technology’s version, and
- Complexity of the underlying code.
Sadly, you can’t take a browser, operating system, or assistive technology manufacturer’s word at good faith. Determining support means performing manual tests to determine what assistive technology actually reports.
What’s the difference between text content and attribute content?
Before we get any further into it, I think it is important to outline the difference between text content and attribute content.
The written words on a website or web app are typically what the W3C calls either heading content or phrasing content. Combined, they make up the vast majority of written content on the web.
Attribute content is content that comes from the value of things like aria-label
, title
, data-*
, etc. Its purpose is for more niche development concerns.
Both text content and attribute content have purpose and utility when creating accessible content for the web.
Why I think overuse of aria-label
is a code smell
There are a few factors to be aware of. Let’s go over each:
1. aria-label
’s varied support when declared on a non-interactive element
First off, aria-label
is intended to only be used on interactive elements, and not non-interactive ones.
If you need a refresher on what HTML elements are interactive, they are:
- Anchors, when the
href
attribute is present, <button>
,<input>
and<textarea>
, with an accompanyinglabel
,<select>
,<details>
,<audio>
and<video>
when controls are present,<object>
, depending on how it is used,- any element with scroll overflow in Firefox,
- any element with the
contenteditable
attribute applied to it, and - any element with the
tabindex
attribute applied to it.
The following declaration demonstrates how ARIA wants aria-label
to be used:
<button aria-label="Save"></button>
While this declaration is an antipattern:
<div aria-label="create a copy"></div>
The Accessible Name and Description Computation algorithm—and the assistive technology that read the content generated by it—are looking for aria-label
declared on an interactive element. Despite this, I commonly see aria-label
used on non-interactive elements such as a div
to attempt to:
- Mimic an interactive element using unsemantic markup, or
- Provide superfluous interaction hints and descriptions.
When you declare aria-label
on a non-interactive element, it is not being used as intended. Because of this, chances are good that it will:
- Not be announced at all, or
- Create a confusing, unexpected, or annoying announcement.
The second bullet point is the one that breaks my heart.
Unnecessary control hints and descriptions almost is almost always a case of someone whose heart is in the right place, but is irresponsibly using ARIA without knowing both:
- Its technical specifications, and
- The negative social implications that come with creating “special” instructions only for disabled people.
2. aria-label
’s known support concerns when declared on an interactive element
Compared to a lot of its brethren, aria-label
enjoys good support. However, this does not mean it has perfect support. Of note from the Accessibility Support page, aria-label
:
- Only has partial support for accessible name computation in Edge with Narrator, and
- Does not convey name changes when focused for multiple browsers (think a play/pause button).
An accessible name derived from aria-label
that changes when its control is focused—which is required in order to activate the control—not announcing this state change is more concerning. This is because it is a common interaction pattern, to say nothing of other issues with the accessible name changing on an interactive element.
The support issue with Edge and Narrator gives me pause, in that they’re both Microsoft products and should theoretically be simpatico.
3. aria-label
’s support concerns when used in a complicated interaction pattern
Grids, Tree Views, Treegrids, and bespoke custom components all are likely culprits. Be suspicious of any component—or series of interrelated components—that move away from things like simple boolean toggles and get into more complicated coordinated logic.
The reason I say this is that the more complicated your interactions become, the less reliable ARIA gets. The reason for this is as simple as it is depressing: ARIA is not a prioritized concern, and therefore has less thorough testing and support.
A practical example of this is a screen reader’s cursor “breaking” when reviewing focused text. Here, it will announce text that is not technically present. This means the onus is on the person using the screen reader to know:
- That this situation is occuring in the first place, and that
- They need to re-trigger reading the node to learn what content is actually present, if any.
Operating with this level of detail requires a good deal of technical literacy for the person using the screen reader, and is well-worth noting.
This point doesn’t even begin to cover things like regressions, and disdainful, willful ignorance. The only way to know with confidence if your complicated interaction pattern works? Test it with actual assistive technology. One way to make those tests easier? Remove aria-label
.
4. aria-label
may override the visible accessible name
Say you have a button with a visible text label of, “Snapshot” and an aria-label
declaration of, “Save software image.
<button
aria-label="Save software image"
type="button">
Snapshot
</button>
To get right to it, this is a failure of WCAG Success Criterion 2.5.3: Label in Name. Someone using voice control software might think that they can say “Click snapshot” and have the button work. Unfortunately, the button’s aria-label
declaration may override the visible text label.
Since aria-label
is code, its value is invisible to anyone who does not have access to source code or developer inspector tools. This means the vast majority of the population have no way of knowing what the accessible name of the button actually is. This forces them to use annoying, repetitive, and esoteric workarounds to get what they need.
5. aria-label
may be applied to something it is forbidden from being applied to
This is in addition to applying it to non-interactive elements.
For better or for worse, HTML is incredibly fault tolerant. You can declare anything on anything, regardless of if it is valid markup or not. Regardless, the browser will try its best to make sure any and all text content you put in those declarations shows up on screen.
ARIA is different. It has a strict grammar, and part of that is certain roles that are forbidden from being assigned an accessible name. The roles are:
caption
,code
,definition
,deletion
,emphasis
,generic
,insertion
,mark
,paragraph
,presentation
,strong
,subscript
,suggestion
,superscript
,term
, andtime
.
So, that “helpful” hint placed on a del
element?
<del aria-label="Sold out on October 20th, 2022">
cherry
</del>
It’s literally not allowed by the language’s own grammar.
6. Some browsers do not translate aria-label
Only Chrome and Edge support updating aria-label
values for translation. The following browsers do not:
- Firefox,
- Safari,
- Chromium browsers other than Chrome or Edge (Vivaldi, Opera, Brave, Arc, etc.),
- Internet Explorer,
- PlayStation Internet Browser, and
- Essentially every other weird one-off browser out there.
If someone requests a language other than the one the website or web app is written in, chances are good aria-label
content will not update to match the new language.
In addition, content like aria-label
s are oftentimes forgotten about as a consideration for translation services, as it is invisible code inserted by developers. This is especially relevant in organization where there is heavy siloing and barriers towards interdepartmental collaboration.
This means that both browsers and people may fail to provide a fully translated experience in situations where aria-label
is utilized.
7. It is difficult to copy aria-label
content or otherwise manipulated it as text
Text content is incredibly versatile. Right clicking on even a single word reveals a whole host of options for things we can do. You can copy it, cut it, define it, search the web for it, translate it, speak it aloud, link to it, print it, clip it, archive it, share it, etc.
This isn’t even counting the more esoteric things you can do like piping selected text into a terminal, creating a spoken phrase playlist entry from it, converting it into a QR code, and other horribly nerdy things I’m not aware of.
Using aria-label
deprives someone of all that utility, unless they are incredibly technically literate. Of note, I’d like to stress the inability to be copied. Copying is a great feature, and is vital for things like researching, writing documentation, crafting how-to guides, or submitting a bug report.
8. aria-label
content will not show up if styles fail to load
Aggressive firewalls, intermittent connection, shiesty service providers, bad caches, browser plugins, content blockers, non-standard browsers, large blocking assets, sloppy JavaScript, compromised ad networks, VPNs, CDN outages, scrapers and archivers, and panicky production hotfixes can all conspire to interrupt your style’s HTTP request.
Despite our industry’s various attempts to kill it, Progressive Enhancement is also still very much a thing. A text content label—visually hidden or otherwise—will always show the interactive control’s accessible name if styles fail to load.
A Progressive Enhancement-friendly approach lets someone understand and take action on things, even under less-than-ideal conditions. An aria-label
providing the accessible name cannot do this.
9. aria-label
may override what aria-describedby
is intended to announce
aria-describedby
allows you to append the text of one element onto another element. This updates the target element’s announcement to be the combination of its initial accessible name and then text of the other element.
In testing, aria-label
’s attribute content will override an element’s text content when creating the new aria-describedby
-derived announcement.
This isn’t necessarily a bad thing per se, although I find it a confusing choice on which part of the overall declaration is honored. Given most developers’ level of familiarity with ARIA, I feel that removing as many potential surprises as possible is a good practice.
10. The First Rule of ARIA exists
The first rule of using ARIA states (emphasis theirs):
If you can use a native HTML element or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.
aria-label
, like the rest of ARIA, has a time and place to be used. However, over-application and misapplication of it can do more harm than good.
Hopefully the previous ten points did their job in illustrating the reason this rule exists.
Well, what should I use instead of aria-label
?
If it is important enough to need words, it is important enough to use text content.