The differences between the ARIA labeling variants

In this bite sized post, I’m going to take the time to explain the differences between aria-label, aria-labelledby and aria-describedby. Before I read the documentation on these attributes, they confused me because they seem so similar, while there are, in fact, some crucial differences between the three. I hope by the end of this post you’ll know when and how to use these three attributes.

Before I go on and explain the differences, I do want to stress something out which is the first rule of using ARIA: Don't use ARIA. This almost sounds like the first rule of Fight club . I’ll be honest here and say that I found this rather confusing in the beginning. Only after reading about it and understanding the intent behind the rule did it click with me. I think it might have been better to name the first rule like this: Prefer native HTML over ARIA. We shouldn’t use ARIA attributes without considering using the semantic HTML element first. I’ll dive deeper into the five rules of using ARIA in a different post since it’s beyond the scope of this topic.

The aria-label

The aria-label attribute is somewhat similar to the <label> element. It doesn't have some of the advantages that the <label> element has, but its purpose is the same. Giving context, through the Accessible Name , to the element it's associated with.

Unlike the <label> element (which is its own element) the aria-label attribute needs to be put on the element itself. It could look like this:

<button aria-label="Close">
    <!-- svg content -->

The aria-label attribute takes a string value, which is then used to create the Accessible Name for the <button> element. The common use case for the aria-label attribute is when we’re not able to use the native <label> element, while still providing context for the Accessible Name.

The aria-labelledby

Although the aria-labelledby attribute may look similar to aria-label, it works quite different. Instead of a string value, it requires the ID of the element we’re referencing.

Let’s say we would want to give meaning to the <button> through the ID of the <svg>element. It would look like this:

<button aria-labelledby="close-icon">
  <svg aria-label="Close" id="close-icon" >
    <!-- svg content -->

We could view aria-labelledby, in this regard, that it’s inheriting the context from the <svg>. The benefit of this approach is that we gain flexibility on how we give meaning to our <button>. The bad part of this approach is that the support isn’t that great .

Another big difference, over the aria-label, is that it could also accept a space-separated list of element IDs. This lets us “build” a certain context from different parts of the UI. For now I haven’t found a practical example to go with this.

The aria-describedby

The aria-describedby attribute is used to add a description for the element it’s used on. I wanted to include this attribute as well next to the aria-label and aria-labelledby since there’s some confusion on what they mean and when we should use them.

<label for="password-input">Password</label>
<input id="password-input" type="password" aria-describedby="password-input-description">
<span id="password-input-description">Password must contain at least 8 characters<span>

In the example I’ve used the aria-describedby attribute to give a description to a password input. And because we’ve attached the description to the input field it will be recognized by the screen reader, enabling it to announce the description after the label of the input.

Voice Over on MacOS would announce something like this: Password, secure edit text. Password must contain at least 8 characters.


Further reading