Accessibility: A Developer’s Perspective

Pooja Chatterjee
Atom Platform
Published in
10 min readJan 25, 2022
Types of accessibility

What is Accessibility?

Accessibility is actually a very important aspect of web development. It ensures that users with diverse abilities are able to access and navigate websites properly. As online services become more common around the world and companies want to have an inclusive end user base, it is important that a website can be accessed by anyone who is authorized to access it. Moreover, in many cases, there can be serious legal repercussions if proper accessibility guidelines are not followed. The World Wide Web Consortium (W3C) notes that “Accessibility is essential for developers and organizations that want to create high quality websites and web tools, and not exclude people from using their products and services” (The World Wide Web Consortium (W3C), n.d.).

Why do we need accessibility?

Accessibility ushers in, with it, the value of inclusivity. Our life has been going online for decades now and the pandemic has accelerated that trend. One of the major industries to go online due to the pandemic was education. Here at Kaplan, we strive to help students and professionals reach their goals and hence it’s very important for us to be able to make our learning platforms accessible.

As a developer, what do I need to do?

During development, a developer should keep in mind that an accessible website should be usable by any person with a visual, audio or motor impairment. For example, a user should be able to navigate the website without the help of a mouse or the sequence of elements read by a screen reader should make sense. This can be accomplished by following a set of development best practices and using tools for testing accessibility. Based on my work at Kaplan where we are building a strategic learning and assessment platform called Atom, I will describe the development best practices and tools to use to be compliant with WCAG 2.0 level AA.

Some Best Coding Practices

So here are some best practices that our development team has adopted to achieve WCAG 2.0 level AA compliance.

Testing your code

There are several ways to test for it. But here are some common tools that you can use:

  1. Screen readers: The most common ones for Mac is Voiceover and for Windows is JAWS ( for Chrome) and NDVA (for FireFox)
  2. Try navigating the website by using keyboard only
  3. Chrome extensions like the AXE tool analyzes a screen and lets you know all the accessibility violations

Using Semantic HTML

Every markup has its specific purpose and should be used for elements that fit that purpose. Screen readers are designed to read the html and so a semantically built website makes more sense as the screen reader reads it. For example an h-tag is read as “heading” and an a-tag as “link”. So if these tags are used in the proper areas of the page, an element meant to be heading will be read as heading and a link as a link.

H-tag Hierarchy

You must have noticed that the default font sizes of h1 tags are greater than h2 tags and that of h2 tags is greater than h3.

H-tag Hierarchy

Visually, the above image tells the user that the test on the top is the most important and sets the theme of that particular screen. The h2 is also important but not as much as the h1 but it describes a section of the page, under which we find the h3 which is the least important. However, this information may not be available to a user with visual impairment, for example. That’s why it’s very important to use hierarchical heading structure while building your page. These tags should only be used for headings. For other elements requiring similar styling, CSS should be used.

Skip Links

Most web pages have a host of header and menu items. When using the screen reader, the user is first taken to these nav items and then to the main content of the page. While this makes sense for a user who wishes to explore the nav items, for someone, who wishes to interact with the main content of the page, the process becomes tedious.

Example of a skip link

Thus a skip link is introduced in the html so that a user using a keyboard or a screen reader can directly go to the relevant section of the page. This element usually remains hidden and is activated only when in focus.

##HTML<a class="skip-main" [href]="url+‘#main’">Skip to content</a>## CSSa.skip-main {left: -999px;position: absolute;width: 1px;height: 1px;overflow: hidden;z-index: -999;}a.skip-main:focus,a.skip-main:active {color: white;background-color: blue;padding: 12px 0px;position: absolute;width: 200px;height: auto;left: 0;top: 0;z-index: 999;}

TabIndex

TabIndex should be used only for interactive elements like buttons, links, dropdowns, etc. If third party elements (like angular or react material elements) are being used which are already tabbable, there is no need for using tabIndex.

Images

Images on a web page can perform two major functions : provide some sort of additional information to the user or be a decorative visual aid. In the former case, to ensure the user with accessibility needs do not miss out on any information, the image should be coded with an appropriate alt-text.

Buttons and Links

Buttons and links are quite similar in the sense that they trigger an event after a click action. However they may perform different functions in a web design vs accessibility. For a user using a screen reader, links usually redirect the user to some other location while a button click performs some action on the same location like saving some data or marking something complete. However, sometimes designs may require the user to be directed to a certain screen via a button. In such cases, if these elements are coded as buttons, it becomes confusing to the visually impaired user. In these cases, the element should be coded as an anchor tag and should be styled to look like a button and vice versa.

<a class="button" [href]="url">Button Text</a>
## CSS.button {color: white;background-color: blue;width: 200px;height: auto;}

When the same button is repeated multiple times on a page, more information should be added to each button. For example you can have a blog page with multiple articles, each followed by a ‘read’ button, the screen reader should be able to detect for which article each read button is corresponding to. To achieve that effect we use ‘aria-label’, ‘aria-labelledby’ or ‘aria-describedby’.

<button class="button"attr.aria-label="{{buttonText}} {{article.title}}">Button Text</button>
OR
<div id="title"> Some Text </div><button class="button" attr.aria-labelledby="title">Button Text</button>

Expansion Panels

Handling expansion panels can be tricky when it comes to both keyboard only users as well as screen reader users. The element that triggers the expand/collapse action should be interactive (accessible through keyboard only). For the visually impaired user, it’s very hard to make out if the expand/collapse button has been clicked and what the current state of the panel is. So in this case, ‘aria-expanded’ can be helpful. Usually paired with a button, the screen reader not only announces whether the button was pressed but also detects the current state of the expansion panel.

##HTML<button class="toggle-button"[attr.expanded]="isExpanded"(click)="toggleExpansionPanel()">Button Text</button>##TypescripttoggleExpansionPanel(): void {this.isExpanded = !this.isExpanded;}

Custom Elements for Screen Readers

Sometimes elements are not read by the screen readers in a manner that provides logical sense or the purpose of the elements on a particular screen. Moreover, when using multiple screen readers to ensure accessibility, all of them don’t read all elements consistently. In the previous example, where we are using a button but we want it to be read as “hamburger menu”. We can introduce an aria-label but if the aria-label is not read properly by all the screen readers, the page will not be accessible. So, in this case, we can introduce a <span> element that reads the custom description of the element and hide it visually, while we hide the actual element from the screen readers using ‘aria-hidden’. So now the visual users will see the actual element and the screen reader will read the custom element.

##HTML<div class="time-spent" aria-hidden="true">{{ timeSpentInSeconds |   timeFormat:'hh[:]mm[:]ss' }}</div><span class="visually-hidden">Time Spent is {{h}} hours, {{m}} minutes and {{s}} seconds</span>##CSS.visually-hidden {border: 0;clip: rect(0 0 0 0);height: 1px;margin: -1px;overflow: hidden;padding: 0;position: absolute;width: 1px;}

Roles and Landmarks

Every element serves a purpose on the screen when it comes to delivering content or services to the user. Thus all elements can be assigned a role. Most elements have a default role associated with them. For example, a <button> tag will have the role button associated. However, if we have a group of buttons that we have under a <div> tag , we can have the screen reader identify the element as a menu or a toolbar, by specifically assigning that role to the div. A comprehensive list of roles can be found here.

<div class="menu" role="menu">  <button class="button1" >Button Text</button>  <button class="button2" >Button Text</button></div>

Similarly, each section of the screen serves a purpose. So the screen can be divided into different landmarks, which are sections of the page where the elements serve a common purpose. Screen readers can use these landmarks to help the users orient themselves with the page or use skip links to navigate to different sections of the page. We have already discussed an example of this earlier with the “Skip to Content” link where the user skips to the section of the page having role=main. We can use similar skip links to help the user jump to the different landmarks of the page. For detailed information on each landmark please visit this link.

Typical landmarks found on a page

Modal/Dialog

Dialogs are an interactive feature of the page which takes the user to a different space on the screen and presents new information which was previously not displayed. Similarly on closing the dialog, the user is returned back to the element which opened the dialog. Although it looks quite simple visually, getting this transition to work seamless on all screen readers proved quite a challenging task. The screen readers need to notify the user when the dialog is open, and continue reading the contents of the dialog instead of the original screen in the background and the focus should switch back to the element that opened the dialog when the dialog is closed. Here at Kaplan we are using angular material dialog and, for the screen readers mentioned previously, the following format works.

<div tabIndex="0" class="modal-container" role="dialog" cdkTrapFocus>  <h2 class="mat-dialog-title">{{title}}</h2>  <mat-dialog-content class="modal-content"></mat-dialog-content>  <mat-dialog-actions class="modal-buttons"></mat-dialog-actions></div>

This is an exception to the tabIndex criteria mentioned previously as the dialog container itself is not an interactive element but it helps shift the screen reader focus to the dialog container. The role=dialog helps all the screen reader identify the container as a dialog. The dialog header should always be h2 as the main page header is h1.

Alerts

Alerts are elements on the page that provide some new information to the user as a result of a user interaction. For example, if the user provides a wrong password, an alert message comes up to notify the user that the information provided by the user is incorrect. However for a visually challenged user that information is not available if the screen reader continues to read the elements linearly. So we need to move the focus to the alert message as soon as it pops up and return to the previous element so that the user can correct the information provided. This is achieved by assigning the role=alert to the notification message element.

<span role="alert" class="error-message">Incorrect Password</span>

There are times where the notification text keeps on changing. For example, for dynamic search, the number of results the search hits keeps on changing as the user adds or removes characters from the search text. There are also times when it’s not necessary to read the notification text immediately. For these scenarios we can consider aria-live. This basically looks for any dynamically changing content on the page. Now aria-live can have two values. When we add aria-live=polite, the notification is announced when the screen reader is idle. If the changes are required to be announced immediately, we use aria-live=assertive. By default, aria-live looks for changes on the entire page. If we want to reduce it to a certain region, we can add aria-atomic=true to the parent element and all the child elements will also come under the live region.

<divclass="book-search-result__alert"aria-live="assertive"aria-atomic="true"role="alert">  <span class="search-message">{{books.length}} books found.</span></div>

Incorporate into the SDLC

It is very important not to look at accessibility as an additional check and incorporate it in the bigger development lifecycle. It should be taken into consideration during the UI/UX design process and the formulation of requirements. On the development side, I find it very effective to add accessibility to the acceptance criteria or the definition of done. Two measures that we take at Kaplan that help us are:

  • Adding subtasks for accessibility development stories in the JIRA board.
  • An additional sanity check for accessibility is added to the PR verification process and should be done by the developer before merging the PR.

Conclusion

In a world, where more and more aspects of our life are being catered online, accessibility plays a vital role as we move into the future. Accessibility propagates the practice of inclusion and support in the ever-growing digital universe. Yes there is a learning curve but it’s not too difficult to implement if we view it as a part of the software development lifecycle. By incorporating these principles our products will be able to reach many more people.

--

--