Accessibility at Instrument is a cross-discipline effort that brings in expertise from development, strategy, design, and production. We hold our work to a high standard—it’s not enough just to innovate and to demonstrate technical skill, but whatever we make should be accessible and inclusive as well.

Accessibility as a Priority

Instrument prioritizes accessibility throughout each project, from the initial scope of work (SOW), through design, development, quality assurance (QA), and deployment. Our typical level of accessibility is Web Content Accessibility Group (WCAG) 2.1 AA compliance and we have also worked with clients to craft WCAG 2.1 AAA-compliant experiences according to their legal and strategic requirements.

Committing to accessibility also means internal education in the form of workshops and documentation, as well as empowering individuals to push for better accessibility on a day-to-day-basis. We ensure that accessibility is called out in SOWs and schedules, and we engage QA teams who will be able to evaluate our work for WCAG compliance. No matter the impairment—visual, motor, hearing, or cognitive—people of all abilities should be able to access our products and sites.

Basic steps and tools

These are some basic expectations. There’s a lot more to accessibility than what is mentioned here, but implementing these is a good step to providing a base level of accessibility to any web project.

We consider these items during design, development, and before approving a pull request.

There are different levels of accessibility support. WCAG 2.1 provides documentation on how to meet these levels. We should always meet level AA criteria at a minimum. The various levels and their requirements are outlined in the How to Meet WCAG 2.1 document.

According to the WCAG, there are four main principles of accessibility, often known by the acronym POUR:

  1. Perceivable - Information and user interface components must be presentable to users in ways they can perceive.

  2. Operable - User interface components and navigation must be operable.

  3. Understandable - Information and the operation of user interface must be understandable.

  4. Robust - Content must be robust enough that it can be interpreted reliably by a wide variety of user agents, including assistive technologies.

Important: Some of the tools mentioned below require sending the HTML and/or development url to a third party service. Consider what that means. Projects involving sensitive data should avoid using those in favor of local options.

Valid, semantic HTML

Remember when people wrote xHTML and people would claim their site’s validity with a badge? As HTML5 became the standard, a lot of validation habits died with xHTML as the validation is much looser. While browsers might be able to visually render a page with poor HTML structure, it’s not as easy for assistive technology. Unclosed tags and incorrect application of attributes can quickly become detrimental to accessibility.

There may be cases where validation errors are required to work around other issues. For example, an inline SVG within a button element can gain focus from tab or clicking. Tabbing through that page would result in both the button and svg gaining focus while only one should. This can be prevented by adding focusable="false" and tabindex="-1" to the svg element. However, those attributes are not currently valid on an svg element.

Validation is an easy task, especially for a static site. Here are a few tools to get started:

  1. W3C Validator
  2. Mozilla HTML5 lint
  3. Grunt HTML5 lint

In addition to documented, testable validation rules, also consider the semantic validation of a document. Make sure to use appropriate HTML elements for layout, content, hierarchy and interaction. Heading order is actually important (h1, h2, h3, etc)—check that the document outline makes sense: HTML5 Outliner Bookmarklet or HTML5 Outliner Chrome Extension. Use buttons for buttons, links for links, footers for footers, etc. NO <a href="#">, EVER.

Automated tests

While automated tests can’t catch everything, they can highlight testable issues—things like invalid link references caused by href attributes whose values are set to “#”, out of order header elements, abusing placeholder attributes instead of providing a proper label, etc.

Note sometimes tests can return false positives or there may be cases where need to ignore the testable case. For example, if there are offscreen headers describing lists of links before a proper h1 element, there will be a warning about it. However, in this case, it may make sense to have an h3 before any h1. It is correct to establish a header level for these cases and use the same level everywhere it applies. For example, all non-hierarchical list header elements in the site header and footer could be h3.

Accessibility browser plugins

There are a number of Chrome plugins to test various accessibility metrics. These are useful both for seeing testable issues and giving a different look into what the browser or an assistive device sees. For example, they can catch missing alt attributes, incorrect header order, color contrast errors, show the document outline, or show all the present ARIA attributes.

  1. Accessibility Developer Tools
  2. WAVE

Keyboard navigation and focus states

An accessible site can be navigated entirely through keyboard usage. This is easy to test. Try tabbing through the page. It should be evident what element is focused at any given time and all actionable elements should be able to receive focus and keyboard events. This is a good test to make sure spans (which don’t naturally receive focus) weren’t bound with javascript to do some click action that should have been implemented with a button element (whose purpose is to trigger actions and can receive focus by default).

If a modal or overlay is opened by pressing a button on the page, there should be a corresponding “close” button on the modal. Pressing the escape key should also close the modal and return focus to the button element on the page that triggered the modal.

Consider interactions where it may be appropriate to jump a user to a different part of the page. For example, if clicking a “load more” button, once that content has filled in, often it is best to focus the first new item that was loaded rather than maintain focus on the button itself.

Ideally, someone less familiar with the project would also test this. It’s easy to assume context when you built it and have an expectation of what should be happening, so watching somebody else use their keyboard to navigate through the site can help surface issues that you may not have spotted or expected.

Focus styles

This is dangerous:

*, *:focus { outline: none; }

Make sure you can always tell what element has the current focus state. This is where focus styles become important. The default focus styles are often removed for aesthetic preferences. It’s important to replace that style with a suitable alternative. Typically, using the same style for both hover and focus works well:

@mixin hover() {
  .hoverable &:hover,
  &:active {

Keep in mind that a fully accessible focus state is indicated by more than just motion and any color-change-only style should meet required contrast ratios.

Managing Focus Styles gives a nice overview of options, links to additional articles and a technique for determining if mouse or keyboard caused the focus.

Keyboard traps

Beware of keyboard traps. Any component on the page that can be focused using the keyboard should also allow for unfocusing using the keyboard. There may be special cases where it is intended to temporarily trap a user (for example, to require input in a modal), but it should be made clear to the user how to exit.

Offscreen focus

Avoid duplicating content for visual users and assistive technology. Sometimes design requirements make that difficult. In that case, make sure the offscreen content obtains the keyboard focus through the tab key while at the same time adding a -focus class with appropriate styles to the visual element. Remove the visual version from the tab index using tabindex="-1" to avoid redundant tabbing.

Skip links are offscreen elements that allow quick navigation to specific parts of a page. Typically they should be the first item in the page tab index. When gain focus, CSS should display them on screen.

Typical targets for skip links include the main content area or navigation but may also include more specialized links such as an about section or cart button.

// Offscreen styles. Typically just use a generic
// .-off-screen modifier class on any elements that
// need this rather than repeating css.
%off-screen {
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  margin: 0;
  overflow: hidden;
  padding: 0;
  position: absolute !important;
  width: 1px;
  white-space: nowrap;

// Use when you want an off-screen element to be
// visible when focused for accessibility.
%off-screen-focus {
  clip: auto;
  clip-path: auto;
  height: auto;
  overflow: auto;
  width: auto;

.skip {
  @extend %off-screen;

  &:focus {
    @extend %off-screen-focus;
    background: $bg-dark-grey;
    color: $type-light-on-dark;
    left: 50%;
    margin: 0 0 0 -100px;
    padding: 6px;
    text-align: center;
    top: 0;
    width: 200px;
    z-index: 10000;

Not all HTML elements receive focus equally. To make sure a target element that doesn’t otherwise receive focus (for example, a div) can be focused, give the element tabindex="-1". A -1 value for the tabindex property is typically used to remove it from the tab index but also has the side effect of making an otherwise unfocusable element focusable.

Unless using javascript to detect mouse vs keyboard interaction, this may be an example of a case where applying outline: none; to the element is useful as visual users could be confused if clicking a content area caused outlines to show up as that is not typical behavior.

Offscreen text

Offscreen text is any text that is not needed in a visual context but is helpful for assistive technology. This is the most bulletproof offscreen CSS:

%off-screen {
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  margin: 0;
  overflow: hidden;
  padding: 0;
  position: absolute !important;
  width: 1px;
  white-space: nowrap;


Any element with the .-off-screen class will be “visible” to assistive devices without being displayed to visual users.

This can be applied to text used to give hints as to the context of elements within the page. A good example is offscreen headers. Typically any HTML list element should be preceded by a header indicating the contents of the list that follows. Most assistive technology can quickly jump between header elements in a page so the headers provide shortcuts through the content. It may also be applied to alternative text based versions of content.

Test Colors

A design should be tested for accessible color ratios both in the design phase and the development phase. There are tools for both cases.

  1. Easy Color Contrast Testing
  2. Chrome Color Contrast Analyzer
  3. Sketch Color Contrast Analyzer

When state is indicated by color, make sure that color-blind users can discern the difference in the UI. Preferably by using words rather than color. See this for a particular egregious example of a poor UI for color-blind users.


Partially-sighted users often need to zoom to read on desktop, laptop and mobile environments. Test that layouts don’t completely fail when the page is zoomed both as a whole using the browser’s zoom facility and with increasing just the text size. General text content will flow without issue. Check any elements that may have an absolute height, width or position set by CSS.

Don’t break zoom on mobile devices—avoid using initial-scale=1.0; maximum-scale=1.0; or user-scalable=no in the viewport meta tag.

Text alternatives

Provide text alternatives to all content. The simplest example of this is alt attributes on images (images that aren’t considered content should have an empty but present alt attribute: alt="").

Beyond alt attributes, images can have longer descriptions. Video and audio should have accompanying closed captioning or textual descriptions. Interactive elements should have text based alternatives that offer the same level of content as the visual counterpart.

Icons and icon fonts

Use inline SVGs/sprites for icons rather than icon fonts.

Icon fonts fall short for reasons of accessibility and support. Screen readers and alternative fonts (such as OpenDyslexic) often have trouble with icon fonts; Opera Mini users don’t have @font-face support and won’t see the icons at all.

Inline SVGs with descriptive text are a more robust icon solution re: accessibility and are scalable, flexible, and spritable.

Provide text-only information about the icon (e.g., for screen readers) via the title and desc attributes on the svg (see also: Text Alternatives).

If the icon is for visual purposes only (such as in a button) and you don’t want to provide a title or desc, hide the icon using aria-hidden="true" and use an offscreen label for the icon and/or button to provide additional context for screen readers:

<button class="drawer-open-button js-desktop-drawer-open">
    <span class="-off-screen">Show topic drawer</span>
    <span class="material-icon" arial-hidden="true">
        <svg class="desktop-drawer-open" xmlns="" width="24" height="24" viewBox="0 0 24 24"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>

Recommended reading:


All form elements should have an associated label, whether that label is visible or placed offscreen for screen reader use. placeholder is not a substitute for input labels.

If a form element is required, it should be labeled clearly as such. If a form is submitted and errors are found in validation, the error should be associated with the corresponding invalid field and aria-invalid="true" should be set on the field. See this article for more on accessible form validation.

Form elements should be placed in logical tab order in the markup so that if a user is tabbing from field to field, it makes sense. For example, a first name field and a last name field should not be separated by an email field. Relatedly, make sure all your form elements are focusable and navigable via keyboard controls.

Custom form controls can often lead to accessibility problems. As much as possible, use native elements for forms and style appropriately. div-style shims for select dropdowns are often quite quirky and not easily navigable via keyboard. If you must create completely custom functionality for your form elements, test thoroughly with screen readers and with a keyboard to ensure accessibility.


ARIA stands for Accessible Rich Internet Applications. It is a set of HTML attributes designed to make content more accessible to assistive technology. It can be used to describe the state of a page, changes within the page, relationships between elements on the page and much more. It’s also easy to get wrong. Start with the basics and test to make sure any attributes are working as expected and not causing more harm than good.

Two common ARIA attributes are aria-role and aria-hidden. aria-role declares the role an element plays on a page. Its values include header, footer, navigation, etc. aria-hidden can be set to true to make an element invisible to assistive technology while still being available to visual users. This can be helpful when providing a text alternative to an interactive element on the page. Do not hide content or functionality from assistive technology if there is not an alternative available to it.

There are many other ways to use ARIA labels and relationships to make UI components such as tabbed interfaces and accordions more accessible, but as noted before, they can be complicated and easy to get wrong, so it’s good to have an understanding of how they work before diving in. A good overview of ARIA roles, relationships, and attributes is available on the Google Developers site.

Screen readers

Screen readers are an essential tool for the many people who rely on them to navigate and use a wide variety of digital technologies. People who use screen readers may be blind or visually impaired, but they may also have other conditions that require them to use this type of software. Additionally, screen readers require practice to use efficiently. Only using one to test a feature probably isn’t going to give a good picture of whether a site actually works well for someone who always navigates the internet with one.


OS X includes VoiceOver support. It can be enabled through System Preference > Accessibility or by pressing cmd + F5. While it’s an easy way to get a general idea of how a site performs on a Mac, it isn’t as robust as others such as JAWS and NVDA.

VoiceOver is also included on iOS devices. Enable VoiceOver on iPhone or iPad in Settings > General > Accessibility > VoiceOver. Apple’s support website has some useful information on how to get started with gestures in VoiceOver.


Android devices include a screenreader called “Talkback”. Talkback tends to be slightly buggy as it’s less mature than VoiceOver, but it’s still worth testing your projects with it. Read more about how to enable and use Talkback.


JAWS and NVDA are widely used on Windows computers. JAWS is expensive while NVDA is free and open-source, so it may be easier to install and test with NVDA if using Windows. Linux has Orca and also BRLTTY for people using a refreshable Braille display.

User testing

User testing with someone accustomed to using assistive technologies is the best way to understand shortcomings in a project. They can give more perspective to what they expect based on prior usage and what either works well or is confusing.

Test with keyboard-only users. Test with users that zoom their browser or zoom only their text size. Test with users that always navigate with a screen reader. Test with color blind users.