How We Made Handshake More Accessible

Posted Sep 20, 2017 by Jason King

Here at Handshake, one of our core company values is that we are Empowered by Diversity. Part of being empowered by diversity means that we make our platform easy to use for the entire diverse population of college students across the country, including those that are blind and visually impaired. Over the past several months, we’ve been busy making updates to our platform to make it more accessible to students with disabilities.

I’ll share how we went about identifying problems, what we did to fix them, and how we used technologies like Webpack to streamline our development.

Identifying Accessibility Problems

The first step to making our platform more accessible was to identify the issues that it currently had. After talking with several students and career centers, it was determined that the majority of our blind and visually impaired users use a screen reader program called JAWS (“Job Access With Speech”). JAWS allows them to read the screen either using text-to-speech or a Braille display.

Before we were even able to try JAWS, we faced the hurdle of being able to install it. The primary operating system that Handshake employees use is MacOS, and JAWS is only available on Windows. After setting up a Windows Virtual Machine and installing JAWS on it, we were able to try out the program. After installing and figuring out how to use JAWS, we quickly realized how much our website could be improved, and were eager to start working on such improvements.

Using a screen reader is a great way to experience how blind and visually impaired users might use our platform. However, it provides little insight into how to fix issues, make sure issues stay fixed, and new issues don’t appear. We rely heavily on automated tests at Handshake, and we really wanted a way to ensure our platform stays easy to use for everyone in an automated way.

To automate Handshake’s accessiblity testing, we now rely on aXe. aXe is an engine used for automatically testing the accessibility of HTML-based user interfaces. Compared to using JAWS, aXe is much easier to install, use in our development environment, and automate. There are multiple ways to use aXe, including extensions for Chrome and Firefox, and integrations with many popular testing frameworks.

How We Use aXe

As I already mentioned, aXe provides a browser extension for both Chrome and Firefox to analyze the accessibility of websites you visit. After installing aXe for Chrome, it is very easy to have it analyze the site you are on. It outputs a concise list of accessibility issues, and gives you information on how to fix said issues.

Output from aXe Chrome Extension

After using the browser extension to identify issues, we fixed the issues and re-analyzed using the extension. Since aXe also integrates with testing frameworks such as RSpec, it was very straightforward to implement automated tests to ensure that our pages stay accessible.

expect(page).to be_accessible.according_to(:wcag2a, :wcag2aa)

By adding this single line of code to our tests, we are able to make sure that any pages that a student visits is accessible to them. Every time a new version of our platform is released, which is multiple times a day, tests like the one above run to ensure that all of the pages that our student users visit are accessible.

High Contrast Mode

Most of the the problems that aXe identified were able to be fixed with little or no visual changes to the page. One area however, the contrast of our colors, was going to need more substantial work. Rather than choosing all new colors for our platform, we decided to create a high contrast version that students can opt-in to.

High Contrast Colors

High contrast mode doesn’t define brand new colors, it modifies our existing color variables using Sass color functions. This allows high contrast mode to require very little maintenance and keep the same general look and feel of standard mode. If the standard orange is changed, the high contrast version will change automatically. Thanks to aXe, we are able to automatically ensure that high contrast mode stays high contrast even with such changes.

$orange: darken($orange, 25%);

We use both the Ruby on Rails Asset Pipeline and Webpack to generate stylesheets for our platform. This means that before high contrast mode, we were generating two CSS files, one for the Asset Pipeline and one for Webpack. After high contrast mode, we now generate four CSS files, standard and high contrast for Asset Pipeline and Webpack.

Generating the high contrast version of the Webpack stylesheet was a bit more involved than the Asset Pipeline counterpart. The first thing we had to make sure of was that all of our colors we were using were defined as variables in a single file. This is good practice for a variety of reasons, but it also made generating a separate high contrast stylesheet much easier.

Once all of our colors are defined in a single place, we can take advantage of the alias feature provided in Webpack. First, we created two Webpack configuration files, one for standard and one for high contrast. In the standard color Webpack configuration, we set the Colors alias to point at the standard colors file. In the high contrast configuration, we can switch out the standard color alias for the high contrast version. This allows the identical stylesheets to be generated, just switching out the colors.

// Load the standard color config
var baseConfig = require("./webpack.config.js");

// Set color alias to high contrast version
baseConfig.resolve.alias.Colors = path.resolve(__dirname, "app/assets/stylesheets/settings/colors-high-contrast.scss");

// Remove existing CSS output
baseConfig.plugins = baseConfig.plugins.filter(plugin => plugin.constructor.name !== "ExtractTextPlugin");

// Set new high contrast CSS output
baseConfig.plugins.push(new ExtractTextPlugin("bundle-high-contrast.css"));

module.exports = baseConfig;

Once we have two separate Webpack configurations, we can modify our continuous delivery system to generate both versions. With all of the correct high contrast CSS being generated, we just need to make sure the correct version is served to the user based on whether or not they opt-in to high contrast mode. With high contrast mode enabled, we are able to use aXe to confirm that we have no more accessibility violations.

def stylesheet_tags
  tags = ""
  if current_user&.is_student? && current_user&.preferences.high_contrast_mode
    tags += stylesheet_link_tag "application-high-contrast", { media: "all", "data-turbolinks-track" => "true" }
    tags += stylesheet_link_tag "manifests/webpack-high-contrast", { media: "all", "data-turbolinks-track" => "true" }
  else
    tags += stylesheet_link_tag "application", { media: "all", "data-turbolinks-track" => "true" }
    tags += stylesheet_link_tag "manifests/webpack", { media: "all", "data-turbolinks-track" => "true" }
  end
  tags.html_safe
end

What’s Next?

The majority of the pages that our student users access on our platform are now free of accessibility issues. In the coming months we will work to ensure all pages that students access are free of accessibility issues and have checks in place to ensure that these pages stay free of accessibility issues. As we continue to grow and add more pages and experiences to our platform, we are committed to maintaining a high standard of accessibility. Our goal is to put students first, and that includes those that are blind or visually impaired.

If you’re interested in building a great user experience, we encourage you to apply for our Full-Stack Software Engineer position. We are especially interested in candidates who are excited about changing the job finding experience for college students across the country!