One thing you can do to improve the accessibility of your work is to always ensure things have accessible names. Unique and useful names, ideally, so that they can be used for navigation. In this post I’ll explain how browsers decide on the names for links, form fields, tables and form groups.
This post is based on part of my talk 6 ways to make your site more accessible, that I gave at WordCamp Rotterdam last week.
When a user accesses your site, the server will send markup to the browser. This gets turned into trees. We’re probably all familiar with the DOM tree, a live representation of your markup, with all nodes turned into objects that we can read properties of and perform all sorts of functions on.
What many people don’t know, is that there is a second structure that the browser can generate: the accessibility tree. It is based off the DOM tree, and contains all meta information relation related to accessibility: roles, names and properties. Another way to say it: the accessibility tree is how your page gets exposed to assistive technologies.
Assistive Technology (AT) is an umbrella term for all sorts of tools that people use to improve how they access things. For computers and the web, they include:
- alternate pointing devices, like a mouse that attaches to a user’s head
- screen magnifiers, they enlarge the screen
- braille bars, they turn what’s on the screen into braille
- screenreaders, they read out what’s on the screen to the user
All of these tools, to work efficiently, need to know what’s happening on the screen. To find out, they access Platform APIs, built into every major platform, including Windows, Mac and Linux. The APIs can expose everything in the OS, so they know about things like the Start Bar, Dock or the browser’s back button. One thing they don’t know about, is the websites you access. They can’t possibly have the semantic structure of every website built into their APIs, so they rely on an intermediary — this is where the Accessibility Tree comes in. It exposes your website’s structure. As I said, it is based on the DOM, which is based on our mark-up.
A handy flow chart
The accessibility tree exposes roles (is this a header, a footer, a button, a navigation?), names (I’ll get into those in a bit), properties (is the hamburger menu open or closed, is the checkbox checked or not, et cetera) and a number of other things.
If you want to see what this looks like on a site of your choosing, have a look at the Accessibility Panel in Firefox Developer Tools, or check out the accessibility info boxes in Chrome, Safari Tech Preview or Edge developer tools.
Accesssible name computation
Names are one of the things the accessibility tree exposes for its objects. What a thing’s name is, gets derived from markup. There are many aspects that can influence this. If you want to know this in detail, check out the Accessible Name and Description Computation Specification.
Unique names help distinguish
Before going more into how to expose names, let’s look at which names we want. What the names are is crucial for whether they are accessible or not.
What if your family has four cats, and each of them is named ”Alice”? This would be incredibly impractical, as it would make communication difficult. “Has Alice been fed yet?”, you might wonder. “Is Alice outside?”, you might ask your partner. Ambiguity is impractical. Yet, this is what we do when our homepage has four news items, with each “Read more” as its link text.
Imagine all of your cats were named Alice (photo: stratman2 on Flickr)
This is very common, sadly. In the WebAIM Million project, in which WebAIM looked at over a million sites and ran automated accessibility checks, they found:
24.4% of pages had links with ambiguous link text, such as ‘click here’, ‘more’, ‘continue’, etc.
Reusing “Read more” as the link text for each news item makes our code and content management simpler, but it provides bad usability for screenreader users. When they use the link shortcut to browse through links on the page, they will have no idea where each links leads them. In the example above, when you ask an AT to read out all links, it will read “Link Read more, Link Read more, Link Read more, Link Read more”.
So, unique and descriptive names are useful to AT users. Let’s look at which HTML can help us provide names. As I said before, the heuristics for determining names are in a spec, but with just HTML providing names for most things is trivial. The following section is mostly useful for people whose HTML is rusty.
The contents of an
<a> element will usually become the accessible name.
<a href="/win-a-prize"> Win a prize</a>
the accessible name would compute as “Win a prize”.
If there’s just an image, its alt text can also get used:
<a href="/win-a-prize"> <img src="prize.png" alt="Win a prize" /> </a>
And, to be clear, if there’s nothing provided, the name would be
null or empty string, so some people would be unable to win any prize.
Form fields get labelled using the
<label> element. In their aforementioned research, WebAIM also found:
59% of form inputs were not properly labeled.
Let’s look at what a labelling mistake could look like:
<div>Email</div> <!-- don't do this--> <input type="email" id="email" />
In this example, the word “Email” appears right before the input, so a portion of your users might be able to visually associate that they belong together. But they aren’t associated, so the input has no name— it will compute as
'' in the accessibility tree.
Associating can be done by wrapping the input in a
<label> element, or by using a
for attribute that matches the input’s
<label for="email">Email</label> <!-- do this--> <input type="email" id="email" />
To give a table a name, you can use its
<caption> element. This is used as the first element in a
Groups in a form
Within forms, you sometimes want to group a set of form inputs, for example a collection of radiobuttons or checkboxes that answer the same question. HTML has
<fieldset> for grouping form elements. To name this group as a whole, use the
<fieldset> <legend>Don't you love HTML?</legend> <input type="radio" name="yesno" id="yes"/> <label for="yes">Yes</label> <input type="radio" name="yesno" id="no"/> <label for="no">No</label>
If you were to inspect this fieldset in the accessibility tree, you will notice that the group is now known as “Don’t you love HTML?”.
What about ARIA?
Those familiar with the Accessible Name and Description Computation spec might wonder at this point: doesn’t ARIA also let us give elements accessible names? It totally does, for instance through the
aria-labelledby attributes. When added to an element, they overwrite the accessible name (if there was one).
Good reasons to prefer standard HTML tags over ARIA include:
- better browser support (a lot of browsers support most ARIA, but all support all HTML, generally speaking)
- more likely to be understood by current or future team members that don’t have all the ARIA skills
- less likely to be forgotten about when doing things like internationalisation (in your own code, or by external tools like Google Translate, see Heydon Pickering’s post aria-label is a xenophobe)
Sometimes ARIA can come in handy, for example if an element doesn’t play along well with your CSS (like if you want a Grid Layout in a
fieldset), or if your (client’s) CMS is very inflexible.
It’s the markup that matters
In modern browsers, our markup becomes an accessibility tree that ultimately informs what our interface looks like to assistive technologies. It doesn’t matter as much whether you’ve written this markup:
- in a
- in Twig, Handlebars or Nunjucks
- as the
<template>in a Vue Single File Component
- exported in the JSX of your React component
- outputted by a weird legacy CMS
It is which markup that determines if your site is pleasurable to experience for AT users. In short: it’s the markup that matters
There’s good chance your site already uses all of the above HTML elements that name things. They have existed for many years. But I hope this post explains why it is worth the effort to always ensure the code your site serves to users, includes useful names for assistive technologies. Markup-wise it is trivial to assign names to all things on our site, the real challenge is probably two fold. It’s about content (do we come up with useful and distinguishable names), and about tech (can we ensure the right markup gets into our user’s DOMs).