ARIA is a specification that defines how we should design interactive features on websites, and describes how to make them accessible.
It explains how to tell screen readers what type of feature (e.g. a tab list with multiple tabs) something is, so when screen readers interact with it they can accurately describe it to users.
There are two main parts: role and ARIA properties.
The roles are when you want to describe an element and explain what it is. For example if you have a custom checkbox item (should probably avoid doing that!) then you might have <div role="checkbox">click to toggle something</div>. Screen readers will then know its not just a div, but a checkbox. (Other important accessibility things such as focusable state are removed from this example).
Then aria properties are properties that you can set on elements, for example <div aria-hidden="true">Screen readers will ignore this</div> (aria properties are only used by screen readers / assistive tech, so setting aria-hidden will hide it only for those). Or <button aria-label="Show more button">+</button> which will let screen readers describe it as “show more button” instead of “plus sign”.
This is something for your developers. Generally if you’re adding functionality via JavaScript (this includes anything in React/Vue/Angular) then you will need to consider ARIA to make it accessible.
What browsers use ARIA?
Assistive technologies use ARIA. So if you have a screen reader (even if its by setting screen reader on in your operating system and then you use Chrome), ARIA will be used.
What can you do with ARIA?
You can use ARIA to tell browsers (screen readers or other assistive browsers) semantic information about elements.
For example you can tell them what an element is labelled as (aria-label="open new window or aria-labelledby="someElementID"), or say if an element is expanded (useful for dropdowns) with aria-expanded="true").
When to use ARIA
Always avoid using aria if possible. There are lots of built in elements in HTML5 - they are designed to already be fully accessible so do not try to reinvent the wheel.
ARIA roles (in detail)
HTML has a lot of built in elements - such as <input type="checkbox" /> or <img src="..."/>.
But it doesn’t have everything - for example tabs. We can recreate tab functionality (often with <div> elements). But unless you use ARIA then screen readers will not know they’re anything special other than a standard <div> element.
So we can use ARIA roles to tell screen readers what type of feature something is. Then the screen reader will tell the user what it is (e.g. a tab list).
Landmark roles
If you can visually see then you can probably clearly make up where the headers of a site site, what the nav is, where the footer is, what a form is.
(note: we should always aim to use built in things like <form> so screen readers will know its a form. But sometimes <div role="form"> is needed.)
But screen readers will not be able to distinguish that. So we should use ARIA landmark roles so screen readers can describe areas of the site correctly.
Maybe for some reason you want to reimplement a checkbox, and instead of <input type="checkbox"> you’ve ended up with a div.
You can use roles such as role="checkbox" to tell screen readers that this is really a checkbox.
Other examples:
role="button"
role="img"
role="textbox"
(always try to avoid using these - the standard HTML5 element for these roles already exist and have correct accessibility already baked in).
Widget Roles
If you create something that has some form of interaction then you should consider the widget roles. They are for when you implement something such as a tab/tablist, a tooltip etc.
The following example shows a composite widget (tab/tablist/tabpanel). Note - this is a very basic example, no aria properties (such as showing what is currently shown tab) are added.
The role="application" role is a document structure role.
In most cases you should avoid setting this unless you really know what you’re doing.
When the application role is applied, it is up to the developer of the page (or application!) to handle all interactions such as keyboard event handlers.
If you set role="application" then screen readers will have no access to default accessibility information (such as labels).
There are lots of ARIA properties. Here is a list…
aria-activedescendant
aria-atomic
aria-autocomplete
aria-busy
aria-checked
aria-colcount
aria-colindex
aria-colspan
aria-controls
aria-describedby
aria-description
aria-details
aria-disabled
aria-dropeffect
aria-errormessage
aria-errormessage
aria-expanded
aria-flowto
aria-grabbed
aria-haspopup
aria-hidden
aria-invalid
aria-label
aria-labelledby
aria-level
aria-live
aria-modal
aria-multiline
aria-multiselectable
aria-orientation
aria-owns
aria-placeholder
aria-posinset
aria-pressed
aria-readonly
aria-relevant
aria-required
aria-rowcount
aria-rowindex
aria-rowspan
aria-selected
aria-setsize
aria-sort
aria-valuemax
aria-valuemin
aria-valuenow
aria-valuetext
You will often change the aria properties as users interact with your features. For example you might set aria-invalid as true when an input value is not valid.
Another example might be setting aria-checked on a checkbox when someone clicks it (remember: you should aim to use <input type="checkbox"> and not reimplement things from scratch)
ARIA live regions (announcing changes)
By default a screen reader will read out all content on a page, and then leave it alone. If you change content, it won’t read the updated content.
You can change this with aria-live (and role="alert" which automatically sets up aria-live).
There are three options:
aria-live="off" - this is the default for most elements, and any changes in text content will not be announced
aria-live="polite" - changes to the text content will be announced at the next time the screen reader is idle - in other words, when it has finished reading out whatever it is currently reading.
aria-live="assertive" - will read out changes to text content and interrupt the screen reader even if its currently reading something out.
Example of ARIA live
<div id="announce" aria-live="polite"></div>
// get a button
const aBtn = document.querySelector('#some-button');
const announceDiv = document.querySelector('#announce');
// when clicking the button, set text content
// in the announce div
aBtn.addEventListener('click', () => {
announceDiv.textContent = 'Read something out to the user';
})
Tips about ARIA live announcements
keep the messages short and to the point
Does the whole region need to be re-read out when it changes? By default it won’t (aria-atomic="false" is the default). But you can set it with aria-atomic="true")
when adding an aria live element, aim to set the initial text empty (and then populate it with the announcement) instead of adding the element with the text content already set.
using role="alert" will automatically set aria-live="assertive"
Found this post useful?
Please consider sharing this link with your work colleagues or on social media. There are no ads on my site, I just want to promote accessibility.
Found an issue? please point them out - let me know if there is a mistake and I'll update it
Follow me on Twitter: @A11yForDevs. I post links to interesting a11y articles and resources.