The term “accessibility” refers to the ease of use of an application for as many users as possible. It often evokes the notion of disability: accessibility is designed to help people with visual or hearing impairments, mobility issues, etc. For many, these are rather niche provisions that generally benefit a small number of people.
But make no mistake! These practices don't just benefit people with permanent disabilities. Haven't you ever activated the subtitles on a video because your environment was noisy or you were learning the language being spoken? Indeed, accessibility is also there to meet the needs of people who find themselves in a disabling situation or are temporarily hampered by illness or injury, as the image below illustrates. Considering this, you quickly realize that everyone can benefit from accessibility improvements.
How do you make an application accessible?
The simple definition of an “accessible” application is that it is easily usable by everyone, including people with mobility, vision, hearing, speech or cognitive impairments (or those in situations with similar limitations). Knowing this, there are several angles to attack to make a resource truly accessible, for example:
- you can navigate using assistive technologies (such as a screen reader) or change the zoom ratio without disrupting the layout;
- text for media content (including video transcripts and alternative text for images);
- it can be used with just one hand, or you can navigate using the keyboard only, without a mouse;
- there aren't too many distractions (such as animations or strobe lights), and instructions are clear.
Let's face it, then, it's not always a straightforward process. However, with a minimum of effort, it is possible to make an application considerably more accessible.
How 10% of the effort delivers 80%* of the result
* not at all a made-up statistic from www.believeme.com
A short interlude: the ARIA case
Before getting to the heart of the matter, let's take a short interlude to talk about a prevalent topic regarding accessibility: the notion of “Accessible Rich Internet Applications”, or ARIA for short. This set of attributes can be added to HTML elements to increase their level of accessibility by modifying the accessibility tree (discussed below). As a result, many people equate accessibility with the presence of ARIA in their code.
ARIA attributes can assign roles, i.e. define an element and what it does. In this example, an element is assigned the role button.
They can also add properties, i.e. characteristics, or create relationships between objects. Here, we indicate that the second element is a label that defines what the first element does.
Finally, they can also be used to set statuses, i.e. to specify the current state of an element. In the latter case, we confirm that the button is not toggled.
For most users, ARIA is invisible since it doesn't affect an application's visual appearance or functionality. Only members of the assistive technology community notice the difference between a product with or without ARIA.
In the eyes of a “common” user, the presence of ARIA changes nothing
Indeed, properly incorporating ARIA attributes into code ensures that assistive technology users receive all the necessary information. And I'd like to emphasize that last word: “necessary information”. Of course, combining all types of ARIA attributes (roles, properties and statuses) in a single line is possible. Still, it is not necessary, or even desirable, to do so. Too much ARIA is no better than none at all.
Don't burden your users with useless information!
When to use ARIA
In 2014, the W3C - the World Wide Web Consortium - published the HTML5 recommendation, which brought significant changes, including the creation of “landmarks”, such as <main>, <header>, <footer>, <aside> or <nav>, and attributes like hidden or required. These elements, coupled with major improvements in the support provided by modern browsers, ensure that ARIA's contribution is now less essential than it once was.
With that in mind, the golden rule when using ARIA is: don't use ARIA. Indeed, adding ARIA does not automatically make a resource accessible because of the risk of poor implementation. While there are, of course, a few exceptions to this rule, they are rare.
Instead, make good use of semantic HTML.
In the example above, the semantic HTML element <button> comes with many features that the ARIA role attribute doesn't provide, without you having to lift a finger to implement them:
- 💪you can place the focus there using the keyboard;
- 💪you can activate it by pressing the space bar and the Enter key;
- 💪 it comes with methods and properties such as disabled.
Semantic HTML
According to W3Schools, a semantic HTML element describes its definition to developers and browsers alike. Let's take a closer look at this definition.
“describes its definition to developers”
What does this part of the above definition mean? Let's take the following example. Try to visualize the appearance of this page.
Is there a header? A side menu? A footer? How can you be sure? Now, look at the following code and try to visualize this page again.
Easier, isn't it? That's what we mean by “semantic HTML describes its definition to developers”. It makes the code much more understandable because each element is better defined. On the other hand, some HTML elements are said to be “non-semantic”, i.e. they act as “ simple containers” or merely describe the visual effect rather than the meaning. This is the case for <div>, <span>, <b>, <i>, and <center> tags. Although using these elements is not strictly prohibited, it is advisable to use them sparingly and ensure that a semantic element doesn't already exist, which does the job better.
There are over 100 semantic HTML elements: <form>, <table>, <article>, <aside>, <header>, etc.
What about the second part of the definition? A semantic HTML element describes its definition to developers...
“and browsers alike”
Semantic HTML tags help automated tools decipher the structure of a page. Browsers, when they go through the code they receive, build the Document Object Model (DOM) and the CSS Object Model (CSSOM), as is well known, but they also build an accessibility tree, which is used by assistive technologies.
Did you know that you can easily visualize the latter via your browser's DevTools? Here's how to do it on Chrome.
-
Visit your favourite website, such as ricardocuisine.com (yum).
-
Open DevTools by right-clicking and selecting “Inspect” or pressing the F12 key on your keyboard (or fn + F12 if you're using a Mac).
-
Find the “Accessibility” tab. You may need to click on the chevrons to see more options and find the accessibility tab (as indicated by the blue circle in the image).
-
If you haven't done so before, check the “Enable full-page accessibility tree” box, then close and reopen DevTools.
-
Visit the “Elements” tab, then click on the accessibility button at the top right to see the accessibility tree (see the very subtle red arrow in the image below).
As previously mentioned, semantic HTML enables the creation of landmarks, which become visible in the accessibility tree. Assistive technologies can then use them to easily jump from one section to another as the user navigates the page. Here's an example of a site section breakdown made visible using the Accessibility Insights tool.
Here are two examples of accessibility trees for a similarly rendered page. In the example on the left, semantic HTML was used sparingly, while in the example on the right, it was well implemented. Note the marked presence of landmarks.
TL;DR
What's important to remember is that one of the most essential elements of digital accessibility is the underlying structure of your pages. When building your site or application, don't just rely on CSS style to construct the elements of your page; use semantic HTML elements, too, since CSS won't create landmarks in the accessibility tree. It's simple, and it makes a big difference.
Implementing semantic HTML is simple and considerably increases accessibility.
React's Fragment tool
If you work with React, you should also frequently use their <Fragment> tag. For a better understanding, let's take a concrete example you may be familiar with: creating a list populated by React components. Please note that this example is heavily inspired by (or even copied from) the official React documentation.
When you make the child component, <Item>, React tells you via an error that there can only be one parent component.
The solution is quite simple: you put a <div> at the root, which makes the problem disappear.
But by doing so, you're “breaking” the list, as it were, by introducing unnecessary HTML tags. A better solution, in a similar case, is instead to use the <Fragment> component (also abbreviated <>...</>), which allows you to wrap a component without introducing new nodes into the DOM.
On the left, you can see the result of a list in the DOM when using the <div> tag, while on the right, this is the result when using the <Fragment>. The semantic HTML is broken in the former case, while it remains intact in the latter.
React Testing Library
Another tool in the React suite worth having in your arsenal and using correctly to facilitate the creation of accessible applications is the React Testing Library.
To quote the official documentation, the library's guiding principle is that the more your tests resemble how your software is used, the more confidence they bring. For this reason, React Testing Library provides features that simulate users' interactions with the DOM, similar to their real-life interactions: finding form elements via labels, finding buttons and links from their text, and so on. By doing so, the library indirectly encourages you to make your application accessible.
Here's a typical test case written with React Testing Library, taken from their documentation. You have a render function, selectors to interact with the DOM (getByRole, findByText) and assertion functions (expect, toBeVisible).
The key to making the most of React Testing Library's accessibility benefits lies in the clever use of the selectors at your disposal. They are divided into three categories:
-
selectors to ensure that HTML elements selected in this way are accessible by all users, browsers and technologies and, thus, most accurately reflect the user experience, including those using assistive technologies (byRole, byLabelText, byText, byPlaceholderText, byDisplayValue);
-
semantic query selectors, which are compatible with HTML5 and ARIA but do not reflect the actual usage of all users since the experience can vary depending on the browsers and assistive technologies used (byAltText, byTitle);
-
test id selectors, which in no way reflect the experience of actual users who cannot see or hear them (byTestId).
This means it's better to use selectors from the first category or those from the second category when this isn't possible. In rare cases, you can use test ids, which the documentation describes as “exit doors”, for cases where obtaining DOM elements according to their label or content doesn't make sense or isn't practical. In fact, by relying too heavily on test ids, you lose the guarantee that your application is accessible. And the fact that you imperatively need them in too many tests may be a sign that your application is not.
The within function
One of the challenges faced when writing frontend tests is having several similar elements within the element under test. In the following example, the getByRole selector detects multiple occurrences of the button and the test fails.
Many developers then resort to data-testid to distinguish between the two buttons, as in the screenshots below. While the test is undoubtedly now fixed, in doing so, we lose the accessibility support provided by the React Testing Library, as mentioned above, considering that test ids in no way reflect the user experience.
Another solution, detailed below, is to use React Testing Library's getAll, findAll or queryAll methods, which don't trigger an error when several similar elements are detected. Instead, these elements are placed in an array and can be selected individually. If I suddenly add a third similar button to the page or remove one, how can I guarantee that the test will always detect the right button?
React Testing Library offers the within utility function to resolve this issue, which allows you to restrict the selector's search to the content of a specific page section.
What's next?
Want to contribute more significantly to Web accessibility but don't know where to start? You can watch this free training created by the Chrome team and external specialists to learn more and discover other learning paths.
Les articles en vedette
Readability of Tests, DSL and Refactoring
Software Development: Understanding What It Is
Cultivating the Growth Mindset: the key to success in software engineering
Soyez les premiers au courant des derniers articles publiés
Abonnez-vous à l’infolettre pour ne jamais rater une nouvelle publication de notre blogue et toutes nos nouvelles.