Accessibility is the practice of guaranteeing that interfaces are designed and developed to be usable by people with disabilities. It is often referred to as a11y due to having eleven letters between the first one (a) and the last one (y).
The first mistake I see people make is to associate the word "disabilities" with permanent disabilities. The truth is, disabilities can be situational, temporary or permanent meaning that we all can experience them on a daily basis.
These are some examples of each type of disability if we consider all the senses that a person can use on a UI:
Situations as commonplace as being in a subway can be considered a situational hearing disability. Considering the previous image, if your app or website requires the user to hear properly, you are not only excluding deaf people, but people with an ear infection, people who works on a noisy environment, and people using public transportation.
The web is accessible by default
As front-end engineers, we choose to break it or not all the time.
All the native HTML elements are built with a purpose, and they accomplish that purpose in the best possible way. As developers, we often build interactions using JavaScript as our first option, making everything work as we need. That way we might be rewriting features that HTML already provides, bypassing the built-in accessibility they have.
The best way to avoid this is to use the right HTML elements for the right purpose and then enhance them. This applies not only to basic elements but also to more complex components. Some native HTML controls that can be used with little or no tweaking are:
<details>
creates an accordion.<dialog>
defines a modal window.<progress>
shows a progress bar.<input type="date">
displays a whole calendar.<input type="color">
opens a complete color palette component.<input autocomplete="one-time-code">
allows to fill the input with an auth code without the need to manually copy it.<form>
submits data to a server.<select>
displays a list of options to choose from.
If what you're implementing works as a button, make it a <button>
. If it works as a link, make it an <a>
. You can change the way it looks using CSS. That's what CSS is for. Avoid creating functionality from scratch using <span>
or <div>
when there are native elements for it. This should be the obvious approach, especially to more seasoned developers.
WAI-ARIA
WAI-ARIA is a set of attributes that add semantics to HTML to let browsers and assistive technologies know what is happening in the UI. It helps to communicate advanced interactions and dynamic content.
Example 1: Button that opens a dialog window
A simple example can be this markup of a button that opens a dialog window using JavaScript. As a human developer, you understand that this button shows/hides the section element, but the browser can't deduce that right away.
<button id="modal-trigger">Open modal window</button>
<section id="modal-content">Content inside modal window</section>
To help the browser understand this better, you can add some attributes. For example:
aria-haspopup
will say "this button opens a dialog".aria-controls
will say "this button affects another element (id)."role=dialog
will say "this is a UI dialog".aria-hidden
will say "remove this from the a11y tree".
This is how it would look like:
<button aria-haspopup="true" aria-controls="modal-content" id="modal-trigger">Open modal window</button>
<section role="dialog" aria-hidden="true" id="modal-content">Content inside modal window</section>
Example 2: Button that closes a dialog window
Use WAI-ARIA only when necessary. Using the right markup is often enough. This is a counter-example of a button that closes a dialog window:
<div role="button" tabindex="0">X</div>
I've seen similar code in production uncountable times. These are some ways to take advantage of the native HTML elements:
- Use
<button>
instead of adding arole=""
to any element. - Keep in mind that
<span>
and<div>
are elements with no semantic meaning. - A
<div>
needstabindex=""
to make it focusable but<button>
is focusable by default. - The text "X" will be read literaly as "X". Use readable words instead. You can always replace it visually with CSS.
Here is the exact same example but using cleaner, accessible code:
<button>Close</button>
WAI-ARIA is like talking with the browser and assistive technologies to give them more information about dynamic interactions and content.
Find more info about it on the MDN documentation.
AOM and DOM
There is an Accessibility Object Model (AOM) in the browser that is built from the DOM tree and updated whenever the DOM is updated.
Here's the unofficial draft.
Adding the attribute aria-hidden
removes the element and its children from the accessibility tree. What also makes the job is using the hidden
attribute, display: none
, or visibility: hidden
. In those cases, aria-hidden
is redundant and not necessary.
User's choice
Making a website accessible is basically giving the users the choice over how they consume your content.
For example, for animations on the UI, you can start with a static element and add an animation only when users have no preference for reduced motion:
.logo {
color: black;
}
@media (prefers-reduced-motion: no-preference) {
.logo {
animation: alternate-colors 1s linear infinite;
}
}
@keyframes alternate-colors {
0% { color: red; }
50% { color: green; }
100% { color: blue; }
}
Tools
Some tools I use to check a11y include, but are not limited to:
- Lighthouse
- contrast-ratio.com compares 2 colors using the guidelines by the W3C.
- Accessibility Inspector on Firefox