Okay so you’re a developer and you keep hearing about the importance of accessibility in all stages of a product, from design to development. You’ve probably heard of aria attributes and want to use them to make your products more accessible. The problem is? You maybe don’t actually know what the heck WAI-ARIA is, otherwise why are you here?
Well, look no further! I’m going to demystify aria attributes for you, show you some about when to use aria and when not to and what their purpose really is.
Estimated reading time: 6 minutes
In this article
There are detailed examples of the following attributes:
What does WAI-ARIA mean?
WAI stands for Web Accessibility Initiative. ARIA stands for Accessible Rich Internet Applications. Not clear, not demystified just yet. Bare with me!
What WAI- ARIA is NOT:
- ARIA is NOT a programming language.
- It is not a magical attribute you add to your html to make it more accessible.
- It is not a substitute for semantic HTML
- It is better to have NO ARIA than BAD ARIA
What is WAI – ARIA for?
Aria attributes are used for screenreaders only, to enhance the usability of a given DOM element or component that was not built with semantic HTML for whatever reason.
ARIA Landmarks & Semantic HTML Landmarks
Semantic HTML landmarks such as <nav>, <main>, and <section> tell screenreaders what landmarks are on the page. The person using the screenreader can navigate the page based on these landmarks to skip past information that is not useful for them.
In the even that you have built a UI without the ability to utilize these semantic HTML5 tags, you can use aria regions to simulate this same exact behavior. Take these roles and their semantic counterparts for example:
- role=”navigation” is equal to the <nav> tag
- role=”main” is equal to the <main> tag
- role=”region” is equal to the <section> tag
ARIA Inputs and Labels & Semantic HTML Forms
If you’re using an input, you should include a label. Using a placeholder alone is not accessible to screenreaders, so a label that goes along with the input is important. To connect a label to an input you have to put a for attribute on the label that matches the id of the input. Below is an example of a semantic form input element:
<label for="first-name">Enter Your First Name Here:</label>
<input type="text" id="first-name" />
When you may need to use ARIA in your form elements
Now let’s say you have built a checkbox in React on one side of the screen and another React component with a block of text on the other. How do you link the checkbox component you made to your block of text? ARIA can help!
// The Text Block Component:
const TextBlock = () => {
return (
<div>
<h2>Notify by email</h2>
<p>Turning this setting on will allow us to notify you of changes to your account by email</p>
</div>
}
// The CheckBox Component:
const Switch = () => {
[on, setOn] = useState(false)
const toggleSwitch = () => {
setOn(true)
}
return (
<button role="switch" aria-pressed={on} onClick={toggleSwitch}></button>
)
}
In the above code you might notice the use of aria-pressed and the role=”switch”. The aria-pressed aria attribute will alert the screenreader whether the button is pressed or not. You may also notice that instead of using a standard checkbox element from semantic HTML, I’m using a button. This toggle button with the aria-pressed attribute will allow me to create a beautiful looking switch, that maybe makes less sense as a checkbox and more sense as a kind of switch. The switch role changes what the screenreader says from checked or unchecked for a checkbox, to on or off.
Below I have changed the code so that I can link the TextBox component to my Switch component. I’m using the aria-labelledby, aria-describedby and id attributes to accomplish this:
const TextBlock = () => {
return (
<div>
<h2 id="notifications-label">Notify by email</h2>
<p id="notifications-desc">Turning this setting on will allow us to notify you of changes to your account by email</p>
</div>
}
// The CheckBox Component:
const Switch = () => {
[on, setOn] = useState(false)
const toggleSwitch = () => {
setOn(true)
}
return (
<button role="switch" aria-describedby="notifications-desc" aria-labelledby="notifications-label" aria-pressed={on} onClick={toggleSwitch}></button>
)
}
As you can see, the aria-labelledby attribute is added to the action component and the id is added to the labeling component. Additionally, I’ve added an aria-describedby attribute to the button and an id to the instructions for this component. What this does is allows the screenreader to read out the label text and then the state of the component to the user. This example would read out as “Notify by email off” or “Notify by email, Turning this setting on will allow us to notify you of changes to your account by email off”.
Check out these accessible checkboxes in this How to make an Accessible React To-do List.
Semantic Buttons & ARIA Buttons
Semantic HTML is alway preferable, but in the event you create a div that acts as a button, and you want the screenreader to know this div behaves like a button, you will need to add the role=”button” to the div. As I said HTML is preferable, so let’s assume you made good life decisions and made a button! You won’t need to add a role attribute because an HTML button has an intrinsic role of button. Fantastic!
But what if your button is just an icon and there is no text? How will a screenreader know what the button is for? You can add an aria-label to the button which will be read out to the screenreader. A trash button could have an aria-label of “trash”. This would read out to the user as “trash pressed” if you’re using the aria-pressed=”true” attribute along with it.
Pro Tip:
If you want to be really inclusive, you can add a span with the text inside the button which is visually hidden with the following CSS. What this will do is ensure translation services can translate the non-visual text for the screenreader. Since the text is on the page the screenreader will read it, but a sighted user won’t see the text.
.visually-hidden {
position: absolute !important;
clip: rect(1px, 1px, 1px, 1px) !important;
padding: 0 !important; border: 0 !important;
height: 1px !important; width: 1px !important;
overflow: hidden !important;
}
Learn how to build accessible Toggle Buttons in React.
Testing ARIA
When you’re building with aria, it’s important to test using a screenreader. This will help you understand the attributes you’re utilizing and whether you’re implementing them successfully or not.
For MACOS
You can turn Voice Over on and off with by pressing Command-F5. If VoiceOver is on, pressing the keys turns it off. You can also slide a finger or swipe right or left on the Touch Bar. From apple support.
You will also want to use control + option + U to show the navigation shortcuts. You can arrow left and right to navigate to the page landmarks we discussed previously, the links, headings and form elements menus. All of this will help you understand how to implement aria attributes effectively.
For Windows
- In Windows 10, press Windows logo key + Ctrl + Enter on your keyboard. In earlier versions of Windows, you may need to press Windows logo key + Enter.
- On the sign-in screen, select the Ease of access button in the lower-right corner, and turn on the toggle under Narrator.
- Go to Settings > Ease of Access > Narrator,and then turn on the toggle under Use Narrator. From Windows support.
To see the landmarks in Windows Narrator, press Narrator + F5
For the headings on the page press Narrator + F6
Finally, to see all the links press Narrator + F7
This allows you to see how aria attributes can make sense of otherwise seemingly purposeless elements.