Aria
It's actually WAI-ARIA, and it stands for Web Accessibility Initiative - Accessible Rich Internet Applications. This is a specification, currently being written by the W3C, which defines additional sets of HTML attributes that provide additional semantics when lacking.
Roles
Roles are at the top of the specification and can come very handy for extending basic semantics. They are defined by adding a role=*
attribute. Note that not all roles are applicable to each elements,
especially when it is implicitly declared: for example, a <aside>
tag has an implicit role value of role="complementary"
and only allows feed
,
note
, presentation
, region
or search
.
A good use-case example would be our Color Contrast tool, which features generated color palettes.
<div role="button" class="hue">
<span class="hue__ref">#FFF</span>
<span class="hue__clipboard">Copied to clipboard</span>
<div class="hue__btns">
<button class="hue__btn">Format</button>
<button class="hue__btn">Copy</button>
</div>
</div>
The <div>
container has to be clickable in order to apply the selected hue to the background. And in this case, the use of a <button>
element is out of the equation, because
they don't allow block-level elements inside them. The only solution is to turn the element into an augmented button, which also works with screen readers, focus states, tab navigation, etc.
Roles can also be used to define landmarks in a web page. Whenever you're using a screen reader, it can summary the layout of a page using landmarks. Try this on VoiceOver by pressing the VoiceOver key + U. This page structure, without specified landmarks would be:
- banner — which stands for
<header>
; - navigation — which stands for
<nav>
; - main — which is self-explanatory;
- complementary — which stands for
<aside>
;
Although, we're missing a lot of the structure information. A great way to fix this would be to add corresponding roles to the important landmarks. Let's add to this list our search engine and our important side navigation:
<header>
<nav>
<form role="search">
…
</form>
</nav>
</header>
<main>
<div role="menubar">
<!-- This role defines our div as a presentation of menu that usually remains visible -->
<aside>
<nav aria-label="Breadcrumb">
<!-- This labels this navigation landmark as a breadcrumb -->
Home > Category > Content
</nav>
<nav aria-label="Table of content">
<!-- This labels this navigation landmark as a table of content -->
…
</nav>
</aside>
<article role="article">
<!-- This roles sets our article, the main content of this page, as a landmark -->
</article>
</div>
</main>
And now, our structure summarized by a screen reader looks like this:
- banner;
- navigation;
- search;
- main;
- complementary;
- breadcrumb navigation;
- article.
And that allows screen reader users to quickly browse your website "at a glance".
States & properties
Aria defines a list of multiple properties that can be applied to an HTML element. Here's the current specification, considering you prefix the defined property with aria-
.
atomic
Set to "true", the aria-atomic
attribute tells screen readers to read out the entire element contents as one atomic unit, not just the bits that were updated. Usually linked to aria-live.
controls
It creates a cause and effect relationship between the identified element(s) whose content is controlled by the current element. A good example would be the buttons from image slider controlling the image.
describedby
This is another labeling technique different than HTML labels or aria-label. You can actually use an element to describe another element, such as an input or an image. This is this exact technique we use in the Design documentation for describing example images in a figure
element with figcaption
.
disabled
Most browsers just skip past disabled fields, and thus won't be read by screen readers. It's a better UX pattern to notify the screen reader that this particular field exists, but is not available, by setting this property to true
.
dropeffect
Related to drag-and-drop, this property indicates what functions can be performed when the dragged object is released on the drop target. This property only accepts a defined list of tokens: copy
, move
,
link
, execute
, popup
.
flowto
It allows a screen reader to be given a different reading order by giving it the next element which has to be read.
grabbed
Also related to drag-and-drop, this state indicates that the current element is in the state of a drag operation.
haspopup
This property indicates that the current element has a popup menu or an underlying menu. A simple example is a dropdown list navigation.
<ul>
<li>Menu element 1</li>
<li aria-haspopup="true">
Menu element w/ dropdown
<ul>
<li>Sub-element 1</li>
<li>Sub-element 2</li>
<li>Sub-element 3</li>
</ul>
</li>
<li>Menu element 3</li>
</ul>
hidden
Once this property is set to true, the screen reader will automatically skip the element and not read it. This can be useful for inline images or SVGs whose purpose is only decoration. For people using inline icon fonts, it may also be useful to use the hidden property on the element containing the character.
invalid
The invalid property allows to be a bit more specific as to why a field is invalid. It uses a list of the following tokens as valid values: grammar
, spelling
, false
and true
.
label
Interface elements can sometimes only be graphic, and not have any content. This is when aria-label comes in the play. We used this technique on a few buttons containing no text.
<button class="js-renew" aria-label="Generate new accessible colors"></button>
labelledby
It is almost exactly the same as a the label property. The only difference residing in the fact that if the labelling text is visible on screen, it should be defined by this property.
<div role="dialog" aria-labelledby="diagTitle">
<h2 id="diagTitle">An error occured</h2>
…
</div>
live
Many websites feature infinite scrolling techniques, such as Twitter or Facebook. Although, screen readers cannot be aware of dynamically loaded content, whether it is through network request or DOM manipulation. Setting this property to true
to the container holding your generated content will allow the screen reader to read the new content.
owns
Correct semantics always imply a parent/child relationship. But in some cases, it might not be possible to create such a DOM relationship. Here's a great and simple example:
<ul>
<li aria-owns="fruits">Fruit</li>
<li aria-owns="veggies">Vegetables</li>
</ul>
<ul id="fruits">
<li>Apples</li>
<li>Bananas</li>
<li>Cherries</li>
</ul>
<ul id="veggies">
<li>Aubergine</li>
<li>Brussels sprouts</li>
<li>Carrots</li>
</ul>
relevant
Tied to aria-live, this property helps telling screen readers what happened in a live-region change. It accepts a list of tokens which can be combined: additions
, removals
,
text
and all
.
Other properties
Above were the main properties you may use on any HTML element. However, more specific properties for specific elements exist as well. They are all defined in Section 6.6 of the WAI - ARIA Specification.