Introduction To Accessible Rich Internet Applications (ARIA)
Using ARIA
ARIA Roles
ARIA roles define what an element is or its purpose in the context of a webpage. These roles are particularly useful when creating custom components that don't have native HTML equivalents. Below are some common ARIA roles with examples of how they can be used.Role="button" indicates that the element is a button. Applied to non-button elements that behave like buttons. Here, a <div> is being used as a button. The role="button" makes it recognizable as a button to assistive technologies. The tabindex="0" makes it focusable, and aria-pressed indicates its state.
<div role="button" tabindex="0" aria-pressed="false" onclick="toggle()">Toggle</div>
Role="alert" indicates that the element contains an important message, such as an error or warning. Used for important notifications that need to be announced immediately. The role="alert" will notify screen readers that this is an urgent message, prompting them to announce it immediately.
<div role="alert">Error: Your password must be at least 8 characters long.</div>
Role="dialog" identifies an element as a dialog box or modal. Applied to elements that serve as modal dialogs. The role="dialog" tells assistive technologies that this element is a dialog. The aria-labelledby attribute points to the title of the dialog, and aria-modal="true" indicates that interaction is limited to the dialog until it is dismissed.
<div role="dialog" aria-labelledby="dialog-title" aria-modal="true">
<h2 id="dialog-title">Confirmation"</h2>
<p>Are you sure you want to delete this file?</p>
<button>Confirm</button>
<button>Cancel</button>
</div>
Role="navigation" indicates that the element is a navigation landmark. Used for groups of links that provide site or page navigation. The role="navigation> helps assistive technology users understand that this section contains navigation links. aria-label provides a description for the navigation region.
<div role="navigation" aria-label="Primary">
<ul>
<li><a href="/home">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
</div>
Role="progressbar" indicates that the element represents a progress bar. Used for elements that visually represent progress. The role="progressbar" designates the element as a progress bar. aria-valuenow, aria-valuemin, and aria-valuemax provide additional information about the current state of the progress bar.
<div role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100">
60%
</div>
Role="tab", role="tablist", role="tabpanel" used together to create tabbed navigation. When building a custom tab interface. The role="tablist" groups the tabs. Each button with role="tab" represents a tab, and aria-controls links it to the corresponding content section with role="tabpanel". aria-selected indicates the currently active tab.
<div role="tablist" aria-label="Sample Tabs">
<button role="tab" aria-selected="true" aria-controls="tab1">Tab 1</button>
<button role="tab" aria-selected="false" aria-controls="tab2">Tab 2</button>
</div>
<div id="tab1" role="tabpanel">
Content for Tab 1
</div>
<div id="tab2" role="tabpanel" hidden>
Content for Tab 2
</div>
Role="menu", role="menuitem" used to create a custom menu or context menu. Custom dropdown menus or context menus. The role="menu" defines the element as a menu, and each role="menuitem" defines an individual menu item.
<ul role="menu" aria-label="Options">
<li role="menuitem">Option 1</li>
<li role="menuitem">Option 2</li>
<li role="menuitem">Option 3</li>
</ul>
Slider indicates an element that lets users select from a range of values. Custom sliders for setting values. The role="slider" defines the element as a slider. aria-valuemin, aria-valuemax, and aria-valuenow specify the range and current value.
<div role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" tabindex="0">
50
</div>
Combobox indicates a composite widget that provides an input field and a list of options. Custom dropdowns or autocompletes. The role="combobox" identifies the widget as a combo box. aria-expanded and aria-haspopup provide information about the dropdown state and its type. The input and listbox roles interact to create an accessible autocomplete.
<div role="combobox" aria-expanded="false" aria-haspopup="listbox">
<input type="text" aria-controls="listbox1" aria-autocomplete="list" aria-activedescendant="option1">
<ul role="listbox" id="listbox1">
<li role="option" id="option1">Option 1</li>
<li role="option" id="option2">Option 2</li>
</ul>
</div>
Form indicates a region of the document that represents a collection of form-associated elements. To designate a specific section of a page as a form, especially in complex layouts. The role="form" identifies the div as a form, and aria-labelledby points to the heading that labels the form.
<div role="form" aria-labelledby="form-title">
<h2 id="form-title">Contact Form</h2>
<label for="name">Name:</label>
<input id="name" type="text">
<button type="submit">Submit</button>
</div>
ARIA States
ARIA states are dynamic attributes that represent the current condition of an element in a web application. They are essential for ensuring that users, particularly those who rely on assistive technologies like screen readers, are kept informed about changes in the state of interactive elements. Below are some common ARIA states with examples of how they can be used.aria-checked indicates the current "checked" state of checkboxes, radio buttons, or switches (Values: true, false, mixed). Custom checkboxes or toggle switches. The aria-checked state communicates whether the checkbox is checked (true), unchecked (false), or partially checked (mixed). When the checkbox is clicked, the state should be dynamically updated to reflect the new status.
<div role="checkbox" aria-checked="false" tabindex="0" onclick="toggleCheckbox(this)">
Agree to terms and conditions
</div>
Aria-expanded indicates whether a collapsible element (like a dropdown menu or accordion) is currently expanded or collapsed (Values: true, false). Collapsible content, such as dropdown menus or accordion panels. The aria-expanded state indicates whether the menu is expanded (true) or collapsed (false). When the button is clicked, the state should be toggled, and the hidden attribute on the menu should be updated accordingly.
<button aria-expanded="false" aria-controls="menu1" onclick="toggleMenu(this)">
Menu
</button>
<ul id="menu1" hidden>
<li><a href="#item1">Item 1</a></li>
<li><a href="#item2">Item 2</a></li>
</ul>
Aria-hidden indicates whether an element is visible or hidden from assistive technologies (Values: true, false). Hiding content from screen readers, such as when content is not relevant or is visually hidden. The aria-hidden="true" state hides the element from screen readers, even if it is visible on the screen. This is useful for decorative elements that don't add meaningful content.
<div aria-hidden="true">
<img src="decorative-image.jpg" alt=""/>
</div>
Aria-disabled indicates that an element is perceivable but disabled, meaning it is not interactive (Values: true, false). Disabling form elements or buttons that cannot be interacted with. The aria-disabled="true" state indicates that the button is disabled, and users cannot interact with it. Unlike the native disabled attribute, aria-disabled can be used on any element and still allows the element to be focusable if necessary.
<button aria-disabled="true">
Submit
</button>
Aria-selected indicates the current "selected" state of an item, such as an option in a listbox or a tab in a tablist (Values: true, false). Highlighting the selected item in a list or tab interface. The aria-selected state indicates which option is currently selected. When a different option is selected, the states should be updated accordingly.
<ul role="listbox">
<li role="option" aria-selected="false">Option 1</li>
<li role="option" aria-selected="true">Option 2</li>
<li role="option" aria-selected="false">Option 3</li>
</ul>
Aria-pressed indicates the "pressed" state of a toggle button (Values: true, false, mixed). Toggle buttons, like bold/italic buttons in a text editor. The aria-pressed state communicates whether the button is pressed (active) or not. This is useful for toggle buttons that maintain a state, such as text formatting buttons.
<button aria-pressed="false" onclick="toggleBold(this)">
Bold
</button>
Aria-live indicates that an element will be updated and that updates should be announced by screen readers (Values: off, polite, assertive). For regions of the page where content changes dynamically, like notifications or chat messages. The aria-live state determines how screen readers handle updates to the content. polite means that the update will be announced when the user is idle, while assertive means that it will be announced immediately.
<div aria-live="polite">
Your download will start shortly.
</div>
Aria-busy indicates that an element or its descendants are being updated and users should wait before interacting (Values: true, false). Used in situations where content is loading or being processed. The aria-busy="true" state lets users know that the element is currently busy with an operation, so they should wait until it is finished.
<div aria-busy="true">
Loading data, please wait...
</div>
Aria-invalid indicates that the value entered into a form field is invalid (Values: true, false, grammar, spelling). For form validation, to indicate fields with errors. The aria-invalid state tells the user that the input is invalid. When validation fails, the state should be updated to true.
<input type="text" aria-invalid="true" aria-describedby="error1">
<span id="error1">Invalid entry. Please try again.</span>
The aria-required attribute indicates that user input is required on the element before a form may be submitted. the aria-required attribute explicitly conveys to assistive technologies that the element is required before a form may be submitted. The required attribute on a semantic HTML form control will prevent the form control from being submitted if no value is present. The aria-required attribute, like all ARIA states and properties, has no impact on element functionality. Functionality and behavior must be added in with JavaScript.
<div id="tbLabel">Email Address *</div>
<div role="textbox" contenteditable aria-labelledby="tblabel" aria-required="true" id="email1">
</div>
ARIA Properties
ARIA properties provide additional information about elements and their relationships to other elements. They are crucial in making web content more accessible, especially for users relying on assistive technologies. Here are some common ARIA properties with examples of how they can be used.Aria-label provides a label for an element when a visible label is not present. When an element needs a textual label that is not visually rendered on the page. The aria-label property gives the button a readable name ("Close") for screen readers, even though the button only contains an icon.
<button aria-label="Close">
<svg>icon.png</svg> <!-- Icon with no visible text -->
</button>
Aria-labelledby identifies the element (or elements) that labels the current element. When an element is labeled by another element, typically for complex structures like form controls or widgets. The aria-labelledby property points to the id of the label element, ensuring the screen reader associates the input with the correct label.
<label id="usernameLabel">Username:</label>
<input type="text" id="username" aria-labelledby="usernameLabel">
Aria-describedby identifies the element (or elements) that describe the current element. When additional descriptive text is provided elsewhere in the document, such as help text for a form field. The aria-describedby property points to the id of the descriptive text, which provides additional information about the input field.
<input type="text" id="email" aria-describedby="emailHelp">
<small id="emailHelp">We'll never share your email with anyone else.</small>
Aria-controls identifies the element (or elements) whose contents or presence are controlled by the current element. When a control element (like a button) affects the visibility or content of another element, such as a collapsible section or dialog. The aria-controls property associates the button with the div that contains the details. This helps screen readers understand that the button controls the visibility of the details.
<button aria-controls="details" aria-expanded="false" onclick="toggleDetails()">
Show Details
</button>
<div id="details" hidden>
<p>Here are more details...</p>
</div>
In the aria-live regions, the global aria-atomic attribute indicates whether assistive technologies such as a screen reader will present all, or only parts of, the changed region based on the change notifications defined by the aria-relevant attribute. When the content of a live region changes, the DOM is traversed from the changed element through its ancestors to find the first element with aria-atomic set. This determines the content that the user should be presented with.
<div aria-live="polite" aria-atomic="true">
<h3>the current score is</h3><span>3 to 0 after the first period</span>
</div>
Aria-valuemin, aria-valuemax, aria-valuenow provides information about the minimum, maximum, and current value of an element, typically used in sliders, progress bars, or spin buttons. For custom controls that require a range of values. These properties define the range (aria-valuemin and aria-valuemax) and the current value (aria-valuenow) of the slider, helping screen readers convey this information to users.
<div role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="50" tabindex="0">
50
</div>
Aria-haspopup indicates that an element has a pop-up menu, dialog, or other popup interface associated with it. For buttons or links that trigger additional content, like dropdowns or modals. The aria-haspopup property tells screen readers that the button will open a dialog. This prepares the user for a change in context.
<button aria-haspopup="dialog" aria-controls="dialog1" onclick="openDialog()">
Open Dialog
</button>
<div id="dialog1" role="dialog" hidden>
<p>Dialog content...</p>
<button onclick="closeDialog()">Close</button>
</div>
The aria-level property of an Element defines the hierarchical level of the Element within a structure. Note, Where possible use an HTML <h1>, or other correct heading levels, as these have built in semantics and do not require ARIA attributes.
<div role="heading" id="main-heading" aria-level="1">
This is a main page heading
</div>
Aria-autocomplete indicates whether inputting text will trigger an autocomplete feature and what kind. For input fields that offer suggestions or completions as the user types. The aria-autocomplete property indicates that the input field will display a list of suggestions as the user types, and aria-controls points to the listbox containing those suggestions.
<input type="text" aria-autocomplete="list" aria-controls="autocomplete-list" aria-expanded="false">
<ul id="autocomplete-list" role="listbox">
<li role="option">Option 1</li>
<li role="option">Option 2</li>
</ul>
Aria-multiselectable indicates that the user can select more than one item from the listbox. For listboxes or grids where multiple selections are allowed. The aria-multiselectable property indicates that multiple items in the listbox can be selected, and each aria-selected property reflects the selection state of the individual options.
<ul role="listbox" aria-multiselectable="true">
<li role="option" aria-selected="false">Option 1</li>
<li role="option" aria-selected="false">Option 2</li>
<li role="option" aria-selected="true">Option 3</li>
</ul>
Resources