A wesbite that is accessibile can be used by "all people, regardless of dissability". A website that is inaccessible is not only one that is turning away potential auidence members and customers, it is also denying them a chance to participate.
When designing a website with accessibility in mind it is helpful to putyourself in the shoes of others. You may find it useful to ask yourself questions along the lines of:
For more information on web accessibility, as well as best practices on addressing accessibility in web design we recommend reading W3C Web Content Accessibility Guidelines.
When we first started looking into accessibility for datayze we realized that our site was a little different. One of the key issues was the fact that we were building interactive tools. Not only did the inital tool interface need to be accessible, if the tool interface changes as a result of user input we also need to insure the new interface is also accessible. Most accessibility checkers out there were only analyzing the static content and ignoring the generated content. Most of the tools out there just weren't sufficient for assuring datayze was accessible.
The second issue we encountered is that we are almost constantly in a development cycle creating new tools. We wanted a tool that could automatically be checking accessibility as we code, that could catch easily correctable issues between full accessibility autits.Thus We decided to write our own automated tool to serve as a sanity check. This article is intended for web developers who may need a little more comtrol over their automated accessibility checks. The code presented here may be sufficient for you, but there may be other use cases we haven't considered because they're not relevant to Datayze. No automated tool will be a perfect solution.
I'm going to say it again because it's so important: The code in this article is not intended to take the place of an accessibility audit!
The following code uses jQuery, so be sure not to forget your include!
Also, we should point out that our method of writing to the console is a little clumsy. We're choosing to display each element that generates a warning as nodeName.id.class, but some elements do not have ids or classes. Thus we may see something like ---- Accessibility Warning: Select.runrate.undefined ... in our console log. For us, that's good enough to track down the offending element, especially since we're only running this code in our testing enviornment. You may choose to log your issues rather than display them on the console.
One of the first things that usually springs to mind when we discuss accesibility is alt tags. (Fun side note, the alt stands for "Alternative information.") The alt tag provides an alternative information for those who can't or don't want to get the information from the image itself. for this usecase we write the function checkAltTags().
The first thing checkAltTags() does is look for all visible images (img) (line 2) and then filter if the alt attribute is undefined.
One way we can navigate a website with a keyboard rather than a mouse is through the tab key. Users who rely on their keybards to navigate websites will often use tab clicks to select the link they want, and then press enter to surf to that link. We want our users to be able to use the tab/enter key combo in place of any clickable event. We do this by creating a function checkTabAccessibility().
checkTabAccessibility() works by looking at all elements in a subselect (We'll get to how the subselect is defined later) and filters out all elements that are not concerning. The ones that are left are the ones we need to be notified about
At datayze we use the pointer cursor to indicate an item is clickable. The first thing that checkTabAccessibility() does is filter out all elements where the cursor is not a pointer (line 3). Each item left is one we want to be reachable via a tab. That means that attribute 'tabindex' must be defined if the element is not tabable by defualt. We do this check in isAccessable(). Inputs and A link items are tabable by default. Anothing else must have a tab index. If it doesn't, we check the element parents to ensure it's just not a stacking issue. (An eample where this happens on Datayze be the header menu above. The cursor becomes a pointer is over the text, but the entire span encompusing the text is hooverable/clicable.)
I've seperated out isAccessable() to make it easier to modify if you want to check something other than I have.
Note, we'll discuss how to ensure the right behavor happens once an item is reached via a tab and the enter is pressed down below
Many of our tools have input fields for user supplied input. To be sure we are inclusive for visually impaired audiance members we need to make sure each input is properly labeled. There are several different ways we can do this. We can have an aria-label attribute or we can use a label tag. We're going to preform this check using checkInputHasLabels(). As before, we start with a subselect of HTML elements and filter out the ones that are properly accessible.
Finally, we need to create a MutationObserver to watch for DOM changes. This is critical for datayze as sometimes our tool interfaces are finalized after the inital document ready. When the MutationObserver detects a DOM change, it builds a selector of elements that could have potentially been modified using getIdentifier(). From there, we call checkAccessibility() which preforms our checks.
While discussing the checkTabAccessibility() function I focused soley on whether or not a clickable element could be reached via a series of tab presses. I didn't worry about whether the element had a corresponding onKeyUp or onKeyDown to match the onClick, because I handle that at run time with the following block code.
Important caveat: Be very careful when triggering a click if you use any kind of ad network. You'll see I do not trigger if the element is a google ad. Automating a click is against many ad networks terms of service and could get you banned.One thing you may have noticed is that code blocks are reachable/selectable via tabs or clicks to facility easy copying. One way to do this is to add the property tabindex="0" to each code element. Another way to achieve this is to add the following code which inserts the property automatically.