Accessibility Best Practices at Uptake

Charlie Thomason
Uptake Tech Blog
Published in
9 min readJul 15, 2019

--

At Uptake, we build software that is functional, flexible, and future-friendly. When building an application, JavaScript component, or Design System, you want to build it once, in a reusable way, following best practices and industry standards, so that it can be adapted to all users and use cases. But, when you want to be “future-friendly”, how do you define “all users” or “best practices”? There is a growing movement of UX designers and engineers who believe that an important “best practice” is to think about “all users” — which includes the more than 20% of the population who have some form of disability.

What is accessibility?

The Web Content Accessibility Guidelines (WCAG) define accessibility as making web content more usable for people with disabilities. Disabled users typically use assistive technologies, such as screen readers (like VoiceOver, which is pre-installed on all Apple devices), to interact with websites and applications. However, content needs to be built in such a way that it can be properly interpreted by these assistive technologies.

Most of us take for granted that you would never find a store that could only be entered via stairs, and that movies, TV, and web video content almost-always have closed captioning. Why, therefore, should web software only be built for people who can use a mouse? Or, who can properly see color? If you have a custom dropdown menu that requires a mouse click to interact with it, how does a user with a motor disability interact with it? Or, if you have a web page that automatically refreshes the content without a full page reload, how does a user with a visual disability know that something has changed?

Accessibility is not just about fixing things for users that need it; it’s about being responsible for the software you deliver and ensuring that it works properly for everyone, not just you.

Isn’t accessibility protected by law?

Many forms of “real world” accessibility are protected under the Americans With Disabilities Act, yet it does not deal directly with internet accessibility — given that, at the time the law was passed, the internet was still in its infancy. U.S. Federal agencies are required to meet certain accessibility standards through Section 508 of the Rehabilitation Act. In Ontario, Canada, the Accessibility for Ontarians with Disabilities Act of 2005 requires that all businesses and organizations have basic accessibility, and is punishable by a fine for each day a violation continues. But, for the rest of the web and application world, the responsibility lies with engineers and designers to follow best practices — the same as they would to ensure their content works on mobile devices.

What are the most common types of accessibility issues?

There are 3 levels of web accessibility compliance: A, AA, and AAA. The following are some of the most common errors you will find, which all pertain to the minimum level A compliance:

  • Form controls must have properly-associated label text.
  • Images and icons must have alternative/hidden text.
  • Pages must have a “skip to main content” link to avoid repetitive navigation menus.
  • Clickable elements that direct the user to a new page must be an anchor tag with a valid href attribute; clickable elements that perform in-page actions must be <button> tags. JavaScript links should not be used.
  • Color must not be essential for understanding or interacting with content.
  • Data tables must have properly-associated column headers.
  • Heading text must follow proper semantic structure.

Additionally, here are some common, basic mistakes that you will find across many websites and applications:

  • Custom interactive elements must be interactive via keyboard.
  • Focus and active styles must not be removed without providing an alternative.
  • Colors must have a sufficient color contrast ratio.
  • Link and button text should make sense, out of context, as to the element’s actual functionality (e.g.: “Click here!”).
  • Text should still be readable when resized by the user.

Finally, here are some slightly more advanced (yet still very prevalent) accessibility issues to avoid:

  • Error text should be properly associated with form controls.
  • Alerts messages and status notifications should have proper role attributes so they are announced by screen readers.
  • Elements that have custom states, such as selected or collapsed, should have the proper attributes to indicate these states — not just indicate them visually.
  • Custom modal pop-ups should automatically place keyboard focus inside the content when opened and prevent keyboard focus from getting lost outside or “behind” the modal.

Accessibility in the Uptake Design System and Component Development Kit (CDK)

In order to ensure consistent accessibility, design, and functionality across all Uptake products, we have two publicly-available front-end development solutions: the Uptake Design System, and Component Development Kit (CDK). The Design System is a set of HTML and CSS templates (no JavaScript) that provide the look and feel for all of our most commonly-used elements and components. The CDK is an implementation of the Design System using Vue.js, which makes it easy to implement these same elements and components in an application with customizable props, events, and content slots. While there is still work to be done to improve the accessibility of these products, they do use semantically-correct HTML and best practices, to ensure a solid foundation for accessibility in all of our applications.

Many of the accessibility issues listed above have come up at some point or another, during the history of the Design System and CDK. In attempting to fix these issues we have a few considerations to keep in mind:

  • Are these accessibility fixes or features automatically built-in in a way that all users will receive them, or are they optional features that users may have to read documentation about?
  • If this component is already in use by applications, can we fix these accessibility issues in a way that won’t represent a breaking change?
  • Does adding these accessibility fixes or features require us to sacrifice or change design elements or other aspects of the functionality?

Here are some specific scenarios we have encountered regarding accessibility issues in the Design System and CDK, and how we addressed them.

Associating error text with form controls

Whenever you have long forms full of text inputs and checkboxes, you’ll often want to implement some kind of validation checks. This typically means that form controls with an error state (e.g.: required field is blank, invalid characters have been used) will have a red error message displayed above or below the field. If a screen reader user navigates through a form using the tab key, jumping from one field to the next, the screen reader would, by default, announce 4 main things about a form control:

  1. The type of form element it is.
  2. The label text (assuming it is properly associated with the input).
  3. The current value of the form element.
  4. Any Boolean states applied to the field, such as disabled, required, etc.

However, it would not, by default, announce error text that appears underneath the form element — as this would be considered an entirely separate element on the page. In order to associate the error text with the input field and give the input an error “state”, we can use ARIA attributes. Here is how the aria-invalid and aria-describedby attributes were used to fix this issue with the Design System and CDK’s text input field:

<label
class="up-ds-form-field__label"
for="design-system-input-id">
<span class="up-ds-form-field__label-text">
Input Label
</span>
</label>
<input
type="text"
class="up-ds-input up-ds-input--error"
aria-invalid="true"
aria-describedby="design-system-input-id-error"
id="design-system-input-id"
/>
<div
class="up-ds-form-field__error"
id="design-system-input-id-error">
This field is required
</div>

As you can see, we give the error text an ID, then use that ID as the value for an aria-describedby attribute on the input. Plus, we use aria-invalid="true" to indicate that the field is in an invalid state.

Navigating through a set of tabs

There are many differing opinions on how best to implement proper keyboard accessibility for tabs — that is, a row of buttons that show and hide different content panes. In the Design System and CDK, this issue was further complicated by the need for a special feature: an overflow dropdown menu. In other words, when the row of tab buttons won’t all fit on the screen, some of the tab buttons will collapse into a dropdown menu.

Uptake Design System Tabs
Uptake Design System Tabs

One way to handle this would be to make sure the “More” button can properly open and close the dropdown menu using the keyboard, and adding ARIA attributes to indicate whether the dropdown is currently open or closed. However, does a disabled user actually care about the “More” button? In this case, the “More” button is really only needed for sighted users so they can visually show and hide the dropdown. For screen reader users, the ideal scenario would be to simply just navigate through all of the tabs one-by-one, ignoring the “Menu” button, as though there was no dropdown at all. As a bonus, I would like to indicate that these are actually “tabs”, not just “buttons”, as well as call out which one is currently-selected. Here the basics of how we implemented that for the Design System (simplified for the sake of example):

<ul role="tablist">
<li role="presentation">
<button role="tab" aria-selected="true">Tab 1</button>
</li>
<li role="presentation">
<button role="tab" aria-selected="false">Tab 2</button>
</li>
<li role="presentation">
<button role="tab" aria-selected="false">Tab 3</button>
</li>
<li role="presentation">
<div class="dropdown collapsed" role="presentation">
<div>
<button role="presentation" tabindex="-1" aria-hidden="true">More</button>
</div>
<ul role="presentation">
<li role="presentation">
<button role="tab" aria-selected="false">Tab 4</button>
</li>
<li role="presentation">
<button role="tab" aria-selected="false">Tab 5</button>
</li>
<li role="presentation">
<button role="tab" aria-selected="false">Tab 6</button>
</li>
</ul>
</div>
</li>
</ul>
.dropdown {
position: relative;
}
.dropdown > ul {
position: absolute;
top: 100%;
right: 0;
}
.dropdown.collapsed > ul {
overflow: hidden;
clip: rect(0,0,0,0);
height: 1px;
width: 1px;
margin: -1px;
}

There are a few important things to call out in this example:

  • Tabs have a role of tab, which causes the screen reader to read them as “Tab 1 or 6” rather than as buttons. The main wrapper has the required parent role of tablist. Non-essential elements used only for styling, such as the <li>s, have a role of presentation.
  • Tabs have an aria-selected attribute of true or false, which indicates which tab is selected.
  • The “More” button has a tabindex attribute of "-1". This means the button will no longer receive keyboard tab focus. The tabindex property should be used sparingly and only ever have an attribute of “-1” (to remove from keyboard focus) or “0” (element can only be focused programmatically with JavaScript). It also has an aria-hidden attribute of true, which tells screen readers to skip over them.
  • In order to visually hide the dropdown list, instead of using display: none, we use the above overflow/clip method that removes it visually but still allows it to receive keyboard focus (elements with display:none or visibility: hidden will be ignored by screen readers).

Conclusion

When working toward making your website or application accessible, it is not necessary to strive for absolute perfection. The important thing is to follow property semantic HTML, user-interface design and, most importantly, change how you think about what you build. Rather than thinking only in terms of the visual output of your product, try to follow the 4 main guidelines of accessibility, using the acronym “POUR”:

  • Perceivable: users can perceive content using their senses.
  • Operable: users can operate interactive content using mouse, keyboard, touchscreen, and other input devices.
  • Understandable: users can understand the content, and it is predictable in its presentation and implementation.
  • Robust: users can choose what technologies they want to use to interact with the content, and it is standards-compliant and compatible across browsers, operating systems, and devices.

For more information, please see the resources below:

Like what you read? Visit Uptake Design System and Uptake.com to learn more about Uptake and the world class apps we’re building for predictive analytics.

--

--