Meaningful labels using ARIA – or not.
by Suzy Naschansky published on
If I had a dollar for every time I've had to tell someone to remove an aria-label
from an interactive control that has actual visible text, I could have bought Twitter! As a former developer and current accessibility consultant, it is my sincere hope that by reading this article, developers unfamiliar with or unsure about this topic will have a better understanding of the differences between aria-label
, aria-labelledby
, and aria-describedby
.
Semantic HTML elements convey meaning - role and state - to browsers and assistive technologies. Whenever you can use an appropriate native HTML element, you should do so. For example, using a <button>
, instead of using a generic element such as a <div>
and then adding ARIA roles and states and properties and JavaScript functions and CSS to make it look and behave like a button, is a much better way to code. In fact, the First Rule of ARIA is: Use HTML. (Credit for that paraphrase.)
When should I use ARIA to label something?
Using this priority of methods for labelling a control list, first ask yourself, “do I really need to use ARIA here?” That is, can you add visible text to your element or programmatically associate existing text using native HTML semantics? There are multiple ways to do this; here are a few.
HTML <label>
tag
Use the for
attribute to tie a <label>
to its input.
<label for="fname">First name:</label>
<input type="text" id="fname">
<label for="lname">Last name:</label>
<input type="text" id="lname">
HTML <fieldset>
and <legend>
tags
Use <fieldset>
and <legend>
tags to group and label radio button and checkbox sets.
<fieldset>
<legend>What is your favorite breakfast food?</legend>
<input type="radio" id="waffles" name="fav_breakfast" value="waffles">
<label for="waffles">Waffles</label>
<input type="radio" id="pancakes" name="fav_breakfast" value="pancakes">
<label for="pancakes">Pancakes</label>
<input type="radio" id="leftover_pizza" name="fav_breakfast" value="leftover_pizza">
<label for="pizza">Leftover Pizza</label>
</fieldset>
HTML alt
attribute for images
Use meaningful alt
text for images, particularly when the image is the only content for a link or a button. The alt
text in the next example is much more meaningful to a screen reader user for understanding the purpose of the link than simply describing the bags of money in the image would be.
<a href="/win-the-lottery">
<img src="bags-of-money.png" alt="How to win the lottery. Heaping bags of money to help prove the point.">
</a>
ARIA should be used only to enhance HTML when necessary, not to "fix" bad HTML. That being said, there are times when it may be necessary to clarify or supplement labeling for various elements in order to make them more accessible for users of assistive technologies such as screen reading or voice control software.
There are some great tips on creating effective and user-friendly names in the tutorial better accessible names that apply to all methods of labeling.
Should I use aria-label
or aria-labelledby
?
TLDR:
- If text for the label is available somewhere on the page, use
aria-labelledby
. - If text for the label doesn't exist on the page, use
aria-label
.
The aria-label
attribute accepts a string of text as its value. The aria-labelledby
attribute takes the value of one or more id
attributes. It's especially important to understand that both aria-label
and aria-labelledby
replace any existing label content for assistive technologies. Let's go over some examples.
Appropriate uses of aria-label
Interactive elements with informative icons or icon fonts that don't have accompanying text all need textual names to be accessible. Some examples are links to social media pages and icon-only buttons such as Print, Download, or Info. The aria-label
attribute works great for these situations. Here, an icon is displayed using CSS for an otherwise empty link:
<a href="..." class="icon-facebook social-icon" aria-label="Facebook page"></a>
You know that "X" button in the corner of a modal? Please, give it an aria-label
! The following example will overwrite the visible text content of "X" and announce as "Close," which definitely makes more sense than hearing "X".
<button aria-label="Close">X</button>
In some cases you could instead provide alt
text that would create an appropriate button or link label (and get bonus points for following ARIA Rule #1!).
<button>
<img src="system-icon-circle-x.png" alt="Close">
</button>
When there are multiple navigation areas on a page, adding an aria-label
to each can help a screen reader user differentiate between the regions and better understand where they are on the page. Don't include the word "navigation" as that is already announced via the <nav>
role.
<nav aria-label="Primary"> ... </nav>
<nav aria-label="Breadcrumbs"> ... </nav>
<div role="navigation" aria-label="Footer"> ... </div>`
Make sure your aria-label
value is meaningful. In this next example, the info button label essentially just describes the button's icon:
<!-- don't do this -->
<p>This makes me want to absquatulate.
<button aria-label="question mark">
<i class="fa fa-question-circle"></i>
</button>
</p>
A much better solution would be to provide relevant content about what the info button does or why it's here:
<p>This makes me want to absquatulate.
<button aria-label="What does absquatulate mean?">
<i class="fa fa-question-circle"></i>
</button>
</p>
Appropriate uses of aria-labelledby
When suitable text for a label already exists elsewhere on the page, aria-labelledby
is the preferred method for labeling (if you must use ARIA). Multiple id
values from other elements are separated by a space within the aria-labelledby
's value to concatenate a single string of text.
Suppose you have a series of news articles on a page, and each article has a link that says "Read more." You can use aria-labelledby
to add more context in order to differentiate between these generic links. Since aria-labelledby
will overwrite the visible text content of the link, you'll need to add the "Read more" text back in as well.
<h2 id="article1-heading">All About Dragons</h2>
<p>I like dragons. Blah blah blah blah blah.</p>
<p>
<a id="article1-read-more" aria-labelledby="article1-read-more article1-heading">Read more</a>
</p>
This will result in the link being announced as "Read more All About Dragons." You could go one step better and rewrite those "Read more" links to be more descriptive for everyone.
When should I skip ARIA for labeling?
As has been noted by Léonie Watson, Steve Faulkner, Eevis and many others, these attributes do not work on every element. These labeling attributes are intended for:
- interactive elements
- structural elements with landmark roles
- widgets with explicit roles
Check out this handy chart of ARIA roles and their requirements for naming.
Adding an aria-label
will overwrite any visible text label that already exists, and adding an aria-labelledby
will overwrite any visible text AND any aria-label
provided. In general, you don't want to add aria-label
when an appropriate visible text label already exists.
<a href="about/" aria-label="About Us">About Us</a>
At first glance, this may seem harmless and it won't throw an error in automated or likely even manual accessibility testing, but what about when your company goes international? You're setting your future-self up for extra work and more headaches when that redundant non-visible label doesn't get translated or updated.
<a href="about/" aria-label="About Us">Sobre Nosotros</a>
Never, ever do this:
<button id="run-button-1" aria-label="Customize Report">Run Report</button>
Sighted users will see the button's visible text label of "Run Report", but screen reader users will hear the button's accessible name of "Customize Report". Presumably "Run" and "Customize" are two different actions!
The problem in the previous example is not limited to screen reader users. Someone using voice control software might say "Run Report" to activate the control, but nothing will happen since that's not the accessible name. Voice control users will have to find a workaround when they need to perform the "Run" action that this button visibly indicates.
The following examples show some additional inappropriate uses of aria-label
; you may as well save yourself some coding keystrokes and time spent debugging, by not doing any of the following bad examples.
Non-interactive elements
<div aria-label="Product Group">...</div>
Don't put aria-label
on a <div>
or other non-interactive element without an explicit role; it does nothing but create tech debt.
Decorative images
<img src="decorative-image.jpg" aria-label="">
An empty aria-label
attribute is not the same as an empty alt
attribute. Use an empty alt
attribute (alt=""
) for decorative images.
Prohibited roles
<p aria-label="Causes of eye twitching"> ... </p>
HTML elements whose implicit roles prohibit the use of aria-label
or aria-labelledby
are listed in the current WAI-ARIA specifications.
What about aria-describedby
?
According to the WAI-ARIA specification for aria-describedby, "a label should be concise, where a description is intended to provide more verbose information." Any aria-describedby
content is announced by screen reading software after the element's label is read out.
The aria-describedby
attribute should be used to provide supplemental content to an element's label – in addition to the label – rather than to label it directly. Examples of this might be to provide "helper text" about input format or other requirements when completing a form field, or to associate an error message with a specific input.
<label for="textbox-1">Date</label>
<input type="text" id="textbox-1" aria-describedby="description-1">
<span id="description-1">Use mm/dd/yyyy format</span>
The use of aria-describedby
in this example will let all users know the format of the date to enter in this text input. This will announce to a screen reader user when focus is placed on the form field.
<label for="username">Username</label>
<input type="text" id="username" aria-describedby="username-error">
<span id="username-error">Username is required</span>
In this example, aria-describedby
will programmatically associate the error message with the text input field, which allows screen reader users to hear the error message when the form field is focused. Sighted users will see the error message next to the text input field when it appears.
No ARIA is better than bad ARIA!
If in doubt, leave it out! Unfortunately, it's too common to find seemingly well-intentioned ARIA labels that actually make things worse for folks using assistive technologies. Meaningful and accurate labels can benefit everyone, including screen reader users, voice control users, users with cognitive issues, and all other users!
Screen reader users don't need "extra" instructions like "click here to activate the button" or "extra" information such as "this is a checkbox" so don't add this type of content into element labels. ARIA labels are only available to browsers and screen reading software, and can cause frustration and extra work for a voice control user when a visible label that doesn't match the accessible name. Generally speaking, don't add labels using ARIA if it provides a different user experience to a particular user group. Don't treat users with a disability differently than you would treat other users.
If something is important enough to add using ARIA, consider whether it should be added for all users. Overuse or misuse of the aria-label
attribute can be indicative of larger problems within a code base or development processes. There is more than one way to write accessible code, but please be judicious in your use of ARIA for labeling purposes and just use native semantic HTML whenever possible.
Resources for further reading
- ARIA Authoring Practices Guide (APG): Providing Accessible Names and Descriptions
- Accessible Name and Description Computation
- Requirements for use of ARIA attributes to name elements
- ARIA in HTML
- The A11Y Project Checklist
One last thing
I want to express my sincere appreciation to Eric Bailey for his excellent editorial suggestions on this article, and to Manuel Matuzovic for putting this whole thing together (again!). Thank you both!
About Suzy Naschansky
Suzy started writing HTML code with version 3.2 but has focused on digital accessibility for the past several years to atone for the inaccessible websites she previously made or contributed to. Shifting left, she is now a Digital Accessibility Consultant/UX Architect in the Twin Cities, Minnesota, USA region. She firmly believes that accessibility is everyone's job and that it's easier to put the blueberries in the muffins before they're baked.
LinkedIn: snaschansky
Twitter: @cfdbchick
Website: naschansky.com