Skip to main content
ocean waves

Blog Post

Building an Accessibility Toolbar with Drupal

In November 2015, a team from Mediacurrent participated in Knowbility’s accessibility hackathon. One of the features we created for the site was an accessibility toolbar. We were able to increase the accessibility of the site immensely with relatively little effort with this small addition.

Accessibility toolbar from the Grey Muzzle site:

Accessibility toolbar used on Grey Muzzle site

 

Components

The toolbar consisted of three components:

Dyslexia - The font used on a site can help or hinder a person with Dyslexia. Fonts that flip d and b or p and q characters with no variation are easily reversed by people with dyslexia. Fonts that have a slight variation between flipped letters are often easier to read. So we created a button in the accessibility toolbar to turn a dyslexia-friendly font, Open Dyslexia (http://opendyslexic.org/), on and off and maintained the font change from page to page via a cookie.

Normal font:

Grey Muzzle site showing default text

Dyslexia font:

Grey Muzzle site showing dyslexia font

High Contrast mode - High contrast mode makes all text very prominent while minimizing everything else (including non-critical images), making it easier for people with low vision to read the page’s text. It is not meant to be pretty. We added a button to the accessibility toolbar to activate high contrast mode and maintained the state from page to page via a cookie.

Grey Muzzle site in high contrast mode

Text Resize module - The text resize module provides three buttons for resizing all the text on the page - one to decrease the font size, one to increase the font size, and one to reset the font back to the default size. We discovered that this text resize module works with font sizes designated in ems and pixels, but not rems.

Additional Considerations

In addition to setting the font sizes for the resize buttons, choosing the specific font used for the dyslexia button, and making the theme changes for the high contrast mode, there were several elements that required additional consideration:

Accessibility principle 1: Considering what an element operates as

The text resize module had the resize controls marked up as links. However, the links were not taking a user somewhere. Instead, they were performing an action - increasing, decreasing, or resetting the text size. One of the principles of accessibility is considering what an element operates as instead of just its visual display. These elements were operating as buttons, not links. Since there were three of them grouped together but acting independently, grouped radio buttons would be more appropriate.

I added role attributes to the containing element and links with a value of radiogroup and radio, respectively. This conveyed them to screen readers as radio buttons programmatically. But because simply adding a role does not actually turn one HTML element into another HTML element, we still had several issues to address.

  • Radio buttons are expected to be activated with the spacebar
  • Only one radio is allowed to be active at a time
  • The expected keyboard navigation of radio buttons is different from other controls.

I added JS logic to allow activation with the spacebar:

$("a[role='radio']").keydown(function(event) {
  var t = $(event.currentTarget);
  handleKeyEnter(t, event.which, setRadio, event);
})
 
var handleKeyEnter = function (t, key, handler, e) {
 if (key === 32) {
   handler(t);
   t.click();
   e.preventDefault();
 }
}

The next step was to add the aria-checked attribute to the three links with the proper value according to selection while only allowing one of the three to be true any time.

var setRadio = function (t) {
  var currentlyChecked = t.parent().children("a[aria-checked='true']")[0];
  if (t.is(currentlyChecked)) {
    return;
  }
  toggleChecked(t);
  toggleChecked($(currentlyChecked));
}
 
var toggleChecked = function (t) {
  t.attr("aria-checked", t.attr("aria-checked") === "true" ? "false" : "true");
}
 

The last piece was to modify the keyboard navigation of the resize links. The expected keyboard navigation through a radiogroup is to tab to the group which puts focus on one of the radio buttons, use the arrow keys to navigate between the buttons, and press tab again to take the focus away from the radio group to the next focusable item on the page. Unfortunately, we ran out of time during the short month to implement this piece so a person needs to tab through each radio button. :-(

Accessibility Principle 2: State needs to be conveyed both visually AND programmatically

Another principle of accessibility is that the state of the control needs to be conveyed not only visually, but also programmatically for those who would be navigating the site with a screen reader. The state was conveyed visually via JS through the toggling of an “.active” class on the button which changed the button’s background color. It was conveyed programmatically through the JS addition of aria-checked and the toggling of its value between true and false.

Below is the code for the contrast button. The dyslexia button’s functionality is similar.

Drupal.behaviors.greymuzzleContrast = {
   attach: function (context, settings) {
 
     var contrasted = false;
 
     // Set aria-checked on first page load.
     var attr = $('#contrast').attr('aria-checked');
     if (attr == undefined) {
       if ($.cookie("contrast")  == true) {
         $("#contrast").attr("aria-checked", "true");
       } else {
         $("#contrast").attr("aria-checked", "false");
       }
     }
 
     // Set the contrast button cookie and aria-checked value.
     function contrastSet() {
       $("body").toggleClass("contrast");
       $("#contrast").toggleClass("active");
       $("#contrast").attr("aria-checked", $("#contrast").attr("aria-checked") === "true" ? "false" : "true");
       if (contrasted == false) {
         $.cookie("contrast", true, {path: "/", domain: window.location.host, expires: 1000});
         contrasted = true;
       } else {
         $.cookie("contrast", null, {path: "/", domain: window.location.host});
         contrasted = false;
       }
     }
 
     // Set a cookie so the contrast setting persists.
     if ($.cookie("contrast") != "undefined" && Boolean($.cookie("contrast")) == true && $.cookie("contrast") != null) {
       contrastSet()
     }
 
     // Activate contrast mode
     $("#contrast").click(function () {
       if ($("body").hasClass("contrast")) {
         contrasted = true
       }
       contrastSet()
     });
   }
 };

 

Summary

These small additions, when implemented properly, can set your site apart in creating a positive experience for users and as a result, increase visits and boost business. It is well-worth the extra effort.

 

Additional Resources: 
Building Accessiblity Into Your Website From the Start | Blog Post 
Easy Ways to Make Your Site More Accessible | Blog Post
Accessibility Best Practices for Content Editors | eBook