Angular and Accessibility

Making the Web Accessible by Thinking Outside the Comfort of Our Eyes

As you know, I’m interested in most things about the web, and I love Angular, and so for this post I thought it would be fun to talk about accessibility. By “accessibility,” I mean designing software and websites using large enough fonts, high contrast colors, big enough buttons (especially relevant in the era of touch screens), making sure all elements have textual descriptions for screen readers, and that everything is navigable and accessible with the keyboard.

This post is based on a talk I just gave at ng-conf, and was inspired by my girlfriend. She’s an optometrist and has taught me a lot about our eyes and our vision.

Accessibility is important because guide dogs don’t know how to use a laptop (yet?)

Common Misconceptions About Accessibility

If you’ve never given it much thought, you might think that it’s hard for differently-abled people to use technology, but of course, this is far from the case! No matter who you are, chances are that technology is going to be a big part of your life––even if you can’t see the screen. Chances are, that won’t even stop you from being a programmer!

But of course, accessibility is not just about blind people. When we get to the age of forty, the lens inside our eye has already lost most of its flexibility, and thus we are no longer able to focus on close objects such as our mobile device or the laptop screen. Sure, there are optic tools that can help — eye glasses, contacts, and sometimes surgeries — but even then, it is still not as good as it used to be. Not only that, but during the course of our lives, the receptors in our retina die (wear sun glasses, they help here!), so our resolution decreases as time goes by no matter what, and this can’t even be fixed with either glasses or surgery. And speaking of receptors, we also need to remember that not everyone has all of them — some people are color blind and can only see certain colors.

My point is that, so sooner or later, we will all be a part of the target audience for accessibility.

Considerations for Accessibility

While adding big buttons to our apps might make sense to you if you’ve ever watched your grandmother tap away on a tablet without her reading glasses, there are some other things you should keep in mind about how users who benefit from good accessibility practices might use your apps:

Screen Readers

If you’ve never seen a blind user using a screen reader in action, then you are probably going to be surprised when you watch this video:

Believe it or not, that’s the speed at which many screen reader users can process and understand information — and some can “read” even faster! It’s our job as web developers to make this information available to them and be meaningful. If we don’t, well, see how frustrating it can be to navigate when there is no textual information about the elements:

Link link link link link link link… maybe catchy as a post-[some musical style] tune, but as info on the web? I don’t think so!

Keyboard-Centric Interactions

When you have a limited vision, limited motor abilities, or even just limited physical space, using a mouse may not be an option. For example, since I’m writing this post on a plane and have limited space, I prefer navigating using the keyboard and the tab key.

As programmers, we usually learn a lot of keyboard shortcuts to improve our effectiveness. Some take it to the extreme and use text editors such as VI, which are all about using just the keyboard — no mouse, just a bunch of keyboard commands.

It’s very much the same for many blind people: they use a bunch of keyboard shortcuts to navigate on their computers. For example, they might use shortcuts to jump between the headings of an article if they just want to quickly skim the information. When we design our apps and web pages with accessibility in mind, we can them them out by making sure they can get to all interactive elements using the tab key, and that we use the appropriate markup (or the role attribute) to distinguish headers, links, and so forth.

Here is an example for just some of the navigation keyboard shortcut in ChromeVox, a free screen reader included in all Chromebooks:

Accessibility Testing Tools

It’s very important to test your apps for accessibility. For example, if you want to test accessibility for a blind user, install a screen reader! I use ChromeVox, which is cross platform. On Windows, you can also use Narrator with Edge (which you can activate by presssing the WinKey+Enter), but I should note that it doesn’t work on Chrome. You can also use NVDA, a free screen reader for Windows which works well with Chrome and VSCode. Mac users can use VoiceOver, which you can enable by pressing Command+F5 (or just ask Siri).

Then, use a blur filter for an experience of a slightly visually challenged person by adding the following style rule to your app’s CSS file:

body { filter: blur(4px) !important; }

With the above blur value of 4px, you should still be able to read some of the texts with larger fonts (such as headings). This is about how you might see at age fifty without assistance (glasses, contact lenses, etc.). If you go up to about 10px, you will no longer be able to recognize any text. The boundaries of different elements (images, paragraphs, links), however, will still be visible.

If you want to test a “totally blind” scenario, it is even simpler — you don’t need any code changes. Simply close your eyes and/or switch the monitor off. I recommend trying to do something meaningful (e.g., if it is a stackoverflow-type app — upvote), and see how far you can get without using the screen or mouse, only the keyboard and screen reader.

As for testing for color blindness accessibility, you can easily simulate it using CSS filters. See how here. Or even better— you can install this Chrome extension to do the work for you:

Google Logo, the Tritanopia edition

p.s. Sometimes playing around with these tools can get you some interesting and fun results, such as a screen reader translator with a heavy Israeli accent!

Case Study: Testing a Star Rating Widget in Angular

Let’s see how we apply accessibility practices in a real-life scenario. We’re going to take an example I had in one of the apps I develop, and work through some accessibility related HTML attributes and considerations.

This was a star rating component, the one that you use to give rating to something between 1 and 5 stars:

Initially, the code for this widget was pretty simple:

If you try to use this component with just the keyboard, you will notice you can’t even get to it with the keyboard. Fortunately, this is super easy to fix — we just need to add tabindex="0" attribute to our span element, and it will make that focusable with the keyboard.

So: whenever you have an interactive element, don’t forget to add the tabindex attribute!

Now I can focus with the Tab key

Great! Now we can focus on the element. However, we still can’t interact with it using just the keyboard. The trick here would be to add a keydown event handler to handle the keyboard events. We will add a (keydown)="onKeydown($event)" attribute to our span element, which will let us implement the event handler in our controller, and then we will add the following code to the control — basically accounting for up, down, left, right— allowing manipulation of this element using just the keyboard:

You could even further improve the user experience by making the numerical keys 1 to 5 automatically set the rating accordingly, but since the code is very similar to the above, I am leaving it as an exercise for you :-)

Congratulations! Our element is now keyboard friendly — that’s a good milestone.

Next step would be to make it screen reader compatible. For that, we are going to use the role attribute, which describes the function of an element. Since there is no value which specifies “star rating,” we are going to use something similar, and specify that it is a slider-like element by adding role="slider" attribute to the element. You can read more about the possible value for the role attribute here.

Finally, we are going to add more information about the element by using the aria attributes. WAI-ARIA let you describe roles, states, and properties for your custom widgets so that accessibility tools can recognize and interact with them (for more about ARIA, see this thorough introduction by Gez Lemon, or this more “how-to” article by Georgie Luhur).

Before we get to it, there an angular-specific thing we need to consider. Generally speaking, when we want to bind to the value of an attribute, we can enclose the attribute name in square brackets, e.g., <a [href]="linkVar">. This will take the value of the linkVar variable from our controller and assign it to the href property of the a element. Some attributes, such as role and all of the aria- attributes, are only available as HTML attributes, but not as JavaScript properties of the DOM object. This implies that we need to prefix them with attr. if we want to bind to them. For example:

<span [attr-role]="isActive ? 'slider' : 'none'"></span>

Equipped with this knowledge, we can now add the ARIA attributes to describe the element for a screen reader. We will start by adding an
aria-label attribute, which will describe the function and the state of our span element: [attr.aria-label]="ariaLabel". We are binding it to the ariaLabel property of our controller, where we will implement the actual logic for determining the label of the element:

get ariaLabel(): string {
if (this.value) {
return this.value === 1 ? '1 star' : `${this.value} stars`;
} else {
return 'No rating';
}
}

Finally, we can add several more ARIA attributes that describe the slider’s range and current value:

<span ... 
aria-valuemin="0"
[attr.aria-valuemax]="stars.length"
[attr.aria-valuenow]="value" />

One final thing: we also want to test this element with the color blindness chrome extension I mentioned above. In this case, the shape conveys the meaning (filled star v.s. empty star), and not the color — so we should be good, unless we use a red background, which will make the stars invisible for red-blind people (even for me, the orange outline on red background is hard to distinguish).

And that’s basically it! In just few minutes of work, we turned our custom input element into an accessible one. Adding the tabindex, role and aria attributes is a breeze (once you know the angular binding trick). The custom keyboard event handler requires a little more work, but, at least for me, it’s still much less effort than I spend on styling my HTML elements…

If you want to dig in further, you can find the final code for the star rating example in this repository. The ng-bootstrap project also has an excellent example of an accessible star rating widget.

Accessibility Takeaways

You should always test your app as a visually challenged person. Now that you know how easy it is, you have no excuses :)

I also recommend you learn about the different aria attributes and start using them. At the very least, you should know how to use thetabindex, role and aria-label attributes. I discovered that just by using these three, you already gain a lot of accessibility value.

Also, as a rule of thumb, if you added a click, mouse event, or touch event listener, it means that your element is interactive, and that you should probably add keyboard event handlers as well. If you’d like to learn more about accessibility on the web, I recommend you watch this great talk by Leonie Watson.

I love Angular, and I love the Angular community. As mentioned earlier, I wrote the first draft of this post on the airplane on my way to ng-conf. So as an awesome community, let’s build accessible apps and set an example for other to follow!