Keyboard accessibility in web applications

September 16, 2015

Modern Javascript frameworks allow us to achieve smooth user experience in our web applications. In fact, "single page applications" (SPA) have increased in the marketplace because of them. Current developers (of course, me too) can't live without using AngularJS, React, Ember, jQuery… and, of course, without Grunt, Node, Bower, Gulp… It is cool and nice. All of us working with the same map of technologies and trying to get the same goal: the best user experience. But, are we really achieving this goal? or are we forgetting about something/someone? Single page applications have important advantages, but these advantages should be available to all users. As Tim Berners Lee said, "the power of the Web is in its universality. Access by everyone regardless of disability is an essential aspect". After many years working on it, I still strongly believe in that so I will try to bring here a first approach on how we can improve the "accessibility" in our applications. Accessibility is about people, not about their capabilities. As soon as we understand it, we start to think in the way in which different people use their computers, their tools, their browsers… and our applications. We are thinking, designing, coding, sharing applications for:

…and there are more situations that we shouldn't forget:

We are also thinking, designing, coding and sharing applications for them, right? All devices that people could need, other than mouse and keyboard, have one thing in common: the way in which they interact with the computer mimics the way in which the keyboard does it. So if the application is not fully keyboard accessible, there will be people that could not be able to use it.

Making the application fully keyboard accessible

This is one of the most important improvements that we can apply to our applications and, at the same time, it is one of the easiest that we can do. In addition, keyboard accessibility is one of the easiest things to test. We only need… our keyboard (yes, the device that is below the screen and has buttons with letters). We have to use the application with it, and putting the mouse away. Usually, to navigate through the interaction elements, we can use the "TAB" and "SHIFT + TAB" keys, and "ENTER" to activate buttons, interactive elements and links, when they have the focus.

What are the problems that we could find? How can we fix them?

While testing web applications with the keyboard, there are a few questions that could arise:

I am tabbing and where is the focus?

When navigating with the keyboard, it is quiet common to see that the element with the focus also has a border that is not there when the focus leave. That border is commonly added by the browser (by using the CSS property "outline") and it is there to allow identify which element has the focus. However, that styling is not always shown (reasons… removed, overwritten, etc.). The consequence is that the user cannot identify where the focus is, and as soon as he starts to navigate through the application, he ask to himself "where is the focus?" This is a very easy to fix problem. The way to do it is by applying styles to the elements that have the dynamic pseudo-class "focus" (http://www.w3.org/wiki/CSS/Selectors/pseudo-classes/:focus). This pseudo-class identifies the status focus of the elements, so we can add styles to them. For instance:

.my-control-element:focus {
      outline: 1px solid #F00;
      background-color: #fafaae;
}

With these simple lines in our CSS we are allowing the user to identify where the focus is. If the styles that are applied by default are not appropriate (according to the design) or are not enough to identify where is the focus (in general, I consider so), we can overwrite and/or add more styles. As a rule of thumb, the designer that creates cool styles to apply to the elements of our application (included styles for the dynamic status "hover") should also create styles to apply to the elements when their status focus. Now that we can identify where the focus is, there is another problem…

Why I cannot access that element with the keyboard?

The application has some cool features and widgets (a nice action bar with collapsible options, a cool dropdown, a charming calendar, a solid sorting mechanism in the tables,…). But we are navigating with the keyboard and we see that they don't receive the focus. What is it happening? The origin of this unexpected behaviour is in the HTML that the application has. We can attach behaviour to any element by using the click event. This event allows to one SPAN element to act as a button, one image could open the calendar, the header cells could sort the rows in the table, and so on. The problem is that the browsers can identify and set the focus in native interaction elements (links, input fields, buttons,…), but they don't in others. The application has interfaces that don´t follow web standards (buttons to fire behaviour or as navigation elements, and links to navigate between locations), so the browser cannot work. For instance, the application could fire one function on click event attached to one SPAN:

<span class="app-button" ng-click="doSomething()">
      Do something
</span>

note: "ng-click" (ngClick) is the is an AngularJS directive that allows to specify custom behavior when an element is clicked. And, how we could fix this problem? Easy, using the right HTML elements in the right place (and according to the standards). If the application needs to have the click behavior, it needs to have a button or a link, and its styling will be something to set in the CSS. So the previous code example could be adapted to:

<button class="app-button" ng-click="doSomething()">
      Do something
</button>

As a rule of thumb, as soon as we need a click event, we need a native interaction element. These elements have been created to achieve it, so let's use them. Ok, I know, it could be there extreme situations in which we cannot use native interaction elements (we are using third party widgets, the project is in advanced status and we can not refactor the markup, etc.). First of all, we should be sure that we cannot do it. In this the case, we could add the tabindex attribute. The content of this attribute allows to control whether an element is supposed to be focusable, whether it is supposed to be reachable using sequential focus navigation, and what is to be the relative order of the element for the purposes of sequential focus navigation (http://www.w3.org/TR/html5/editing.html – attr-tabindex). The value of tabindex attribute must be a valid integer and we could use it to allow to one element to get the focus.

Most of the cases in which we could need to add tabindex , the value to use will be zero:

<span class="app-button" ng-click="doSomething()" tabindex="0">
      Do something
</span>

Now, all the elements that need the focus can get it, and we can see where is the focus when they have it, but…

Why the "ENTER" key does not fire the behaviour?

As I have mentioned before, it is quiet common to use the click event to fire behaviour, but the problem is that the "click" can be only executed with the mouse. So the element can get the focus, but cannot get the event. The click event is device dependant, so what should we do? Again, easy problem to fix by adding keypress event. This event can be added and it will be fired when any keys pressed in the keyboard. The only thing to take care is to be aware of which key should be used to do it. Why?… If we duplicate the way in which the click event is working, all keys will fire it. To prevent this unwanted behaviour, we could check which key is being pressed by accessing to the event object and checking its properties. For instance, we could detect if the pressed key is te ENTER key:

function doSomething(event) { 
    var keycode = (event.keyCode ? event.keyCode : event.which); 
    if(keycode !== 13){ // code for ENTER key
        return; 
    }  
    //do something...
}

Check https://w3c.github.io/uievents/ to view the current status of "UI Events Specification". Ok, but we have discovered that there is a cool styling tooltip that is shown when the mouse is over one icon or a menu that is collapsed and it is shown when the mouse is over one link. How can we achieve this behaviour with the keyboard?… by setting other kind of events to fire it. For instance, when one element gets the focus, there is a focus event that is fired. We could add that behaviour to it (remember that the element should be able to get the focus). We can see the focus, we can use the keyboard to navigate through all interaction elements and we can use whole application with it. One last problem that we could find now is that we have to press the tab key many times to arrive to the button that we want to press. If we could use the mouse, we could scan visually the page and click in the item we want. But if there is a long list of links (for instance in a menu), and we only can use the keyboard, the task could spend an unacceptable time, so…

Do I have to go through all links, buttons, etc., always?

The answer is no, or at least, it could be not always. Assistive technologies can take advantage of the markup that the application has and offer it to the user. For instance, if the application uses a correct hierarchical heading structure, the tool could extract it as a map and the user could navigate to the section he wants. Another important way to collaborate in reducing the effort of a long tabbing path is to group set of links in a list (i.e. the main menu). For instance, the screen readers can alert the user that is entering in a list, and he could choose to jump to the end of it. At the end of the day, what we need to do is to use the web standards in the way in which they were created and according to the W3C recommendations. But there are more options. One that have been used for years is to include "skip navigation links":

These links could be hidden by using an accessible technique with CSS and, as soon as they get the focus, be shown. By this way, the user will have a way to skip areas of content and go directly to the point that he wants.

Conclusion

The web applications have to be accessible with the keyboard alone to ensure the way in which we are implementing functionality is not a barrier. To achieve this goal we only need to test the application with our own keyboard, use the right HTML elements according to the web standards, add some improvements and keep in mind that there are lots of ways in which the application could be used.

About the author: Jorge Rumoroso
Comments
Join us