Every person I’ve worked with has agreed that making the web more accessible is a good thing. We don’t want to disservice any of our users.
However, accessibility is nuanced, the work is not always straight forward, and responsibility can be unclear. After all, building websites requires many steps, and accessibility is impacted by the decisions at each stage; design, development, content creation.
It would be great if everyone was an accessibility expert, but that’s probably not going to happen. Becoming an expert is a full time job.
If you’re lucky, you might have one solid person on the team who advocates and educates. But that is not good enough.
So in addition to (not instead of) having dedicated people thinking about accessibility, we must provide tools that make it easier for teams to do the right things and/or harder to do the wrong things.
Ideally, we will meet be people where they work by integrating into the tools they already use. It’ll makes it much more likely that they actually use them.
Let’s make accessibility work intuitive where it needs to be and automatic where it can be.
Some Background on Accessibility
The governing body for accessibility standards is the Web Accessibility Initiative (WAI). They produce and maintain the Web Content Accessibility Guidelines (WCAG) which outline standards for web accessibility (in case that wasn’t already obvious).
A different organization called WebAIM publishes an annual report called “The WebAIM Million“. It’s focus is to measure the accessibility of top 1 million websites and report the trends they find.
According to them, as of February 2021, we’re not doing a great job.
Across the one million home pages, 51,379,694 distinct accessibility errors were detected—an average of 51.4 errors per page
Here are the most common issues discovered, along with the percentage of pages that they occurred on.
- Low contrast text: 86.4%
- Missing alternative text for images: 60.6%
- Missing form input labels: 54.4%
- Empty links: 51.3%
- Missing document language: 28.9%
- Empty buttons: 26.9%
It’s important to note that these numbers are based on WCAG conformance metrics that can be automatically measured by machines. Those metrics don’t necessarily account for all accessibility issues. Nonetheless, it’s helpful to know where we stand.
With all that in mind, let’s take a look at the things we can do to address these issues across our teams.
Accessibility Tools for Designers
The earliest stage to start addressing accessibility issues is probably the design phase.
The work done before design is low fidelity and likely to change. But design decisions are more likely to stick so it’s a good early stage to catch issues.
Unfortunately, most accessibility issues stem from code, not design. But if we look back at the list of most common issues, we will see that the number one problem is related to design: low contrast text.
According to the WCAG, the criteria to pass AA standards for color contrast is…
The visual presentation of text and images of text has a contrast ratio of at least 4.5:1, except for the following:
Which means, if you were creating a design with a badass background color like, oh, I don’t how, how about #BADA55
, in order to pass AA standards, your foreground text color would have to be…
Well, I have no idea. I’d be surprised if anyone could tell you off the top of their heads. And that’s the point.
It’s very difficult for designers to just know what color combinations are acceptable.
There are plenty of tools to help you compare two colors. contrastchecker.com shows plain and simple how two colors compare. Whocanuse.com is similar and has the added features of showing common visual impairments.
These tools are great, but they aren’t what I mean by meeting people where they are. I don’t want to introduce new tools, I want to integrate into existing workflows.
The best tool I can recommend for the job is Stark. It offers accessibility tooling plugins for Figma, Sketch, and AdobeXD. With it, designers can begin to address accessibility issues without changing context.
That’s a good thing. It won’t solve problems over night, but it has a better chance than asking someone to step out of their flow.
In addition to that, there are a couple other tools I recommend. They don’t integrate into design tools (at least no to my knowledge), but they do help when dealing with specific problems.
If you are starting to design a color palette from scratch for generic colors (not brand colors), Accessible Palette is a good start. It provides several common colors and permutations along with the WCAG ratings for text on top of those colors.
If you already have a set of predefined colors (like brand colors) Accessible Brand Colors let’s you add colors and presents a gird layout showing which combinations pass WCAG conformance.
Finally, it’s quite common that you want to use a brand color as a background, but the combination with the text color is not accessible. Accessible Color Generator is an awesome tool that will suggest a close alternative color to use. Many times, I can’t really tell the difference (then again, I’m not a designer).
Accessibility Tools for Developers
Code has the largest impact on accessibility which means developers carry the most responsibility.
Once again, several tools can take markup or a URL and spit out an accessibility report. WAVE by WebAIM is probably the best I’ve found, but it has the same flaw as most color contrast checkers. It relies on developer breaking out of their flow to use a different tool.
Instead of asking our developers to go to the accessibility tools, we can bring the accessibility tools to the developers.
Editor Plugins
For developers using VS Code, for example, there are two excellent plugins that will notify the developer of any accessibility issues with their code. axe Accessibility Linter and webhint have helped me catch and fix many errors without having to keep everything in my head. In fact, they’ve even help teach me about certain accessibility issues I didn’t know about.
Editor extensions are great to get some developers on board but they aren’t without flaw. To have the same impact across the team would require that everyone uses the same IDE with the same extensions installed and the same settings. Sure it’s possible, but I think that does more harm than good. I prefer that sort of thing to be opt-in.
Frontend Frameworks
Modern frontend frameworks have adopted a component-based paradigm. As a result of building everything as components, we can tackle accessibility needs in a single place and address accessibility wherever the component is used.
Take, for example, a component we’ll call AppInput
that wraps an <input>
tag. We can use this component to enforces that all the necessary markup is needed to make an accessible input, and any developer that uses that component will get those benefits without needing to be an expert. That’s great!
For example, we may want to enforce that every input has a label. Unfortunately, as component authors it’s not possible for us to know what an inputs label will be. That is for the component consumer to decide when they add the AppInput
component to a page.
Most component-based libraries also have the concept of “props” as a way to pass data to the component like this <AppInput label="my label" />
. In this example, label
is a prop.
One thing we can do to enforce accessibility is log a warning to the JavaScript console any time out component is implemented without a label. We can do that with prop validation.
Vue has prop validation built in and React has the prop-types library. You could use TypeScript as well, but it’s not quite as robust.
In addition to validating props, we can provide optional props with default values. If the developer consuming the component wants to use the prop, they may. Otherwise it will fall back to a default.
A good example for this use case is an id
attribute. An input should always have an ID attribute. It’s the best way to attach a form to a label.
However, we don’t really need to think of a new ID for each input. We can use JavaScript for that. If the consuming developer provides an ID for the input, we should obviously respect that decision and use it. But if they don’t, why not generate one randomly and use that? After all, browsers and assistive technology don’t care if an input has an ID of “first-name” or “dg234d”.
Finally, it’s not always necessary to build the components from scratch. There are several component libraries out there that are ready to go and have already implemented accessible markup or functionality.
Several of the more popular libraries have already accounted for that, but if you are looking for completely unstyled solutions that offer more design flexibility, here are some options:
- React: Reach UI
- Vue: Vuetensils (I made this one)
- Web components: Lion
Stylesheets
This last part focuses on a11y.css
and the concept is super cool. It’s a CSS library that highlights elements on a page that may have accessibility issues. So it basically let’s the browser engine do the work for you.
Obviously you don’t want to include this sort of CSS library in your production website, but I can think of two ways it could be used.
If you have a build process that’s capable, you could check whether the environment is production code or development code and only include the library during production builds.
Or, you could find a way to include the library only on a staging site. That’s probably even better because it would mimic production more closely.
Accessibility Tools for QA & Code Review
Some companies don’t want their code being automatically deployed to production without someone’s eyes checking that everything still looks good. To make sure things are in place, we have a few options:
- Code review: someone that did not write the code reviews the code and approves it before it gets merged.
- Staging environments: deployments that mimic production environments as closely as possible, but at a different location.
- QA teams: engineers that manually test to make sure everything looks and works as intended
Code review provide a great place to look for accessibility issues, but not all teams have a dedicated accessibility expert to review all code. Or maybe they do, but there is a lot of code to review.
Fortunately, there are tools like Accesslint which run accessibility checks on your code during pull requests. It can be a nice, easy way to add some automated checks in addition to human checks.
We can also give our QA engineers some help by sharing axe DevTools by Deque. By it’s nature, manual testing happens in the browser, so it’s very convenient to have a browser extension that can test accessibility for you.
Accessibility Tools for CI/CD & Deployment
We’ve looked at a lot of tools that help humans on our teams improve accessibility but those tools have one flaw; they rely on humans.
As mentioned before, the tools we introduce should be opt-in choices. That’s great for the team, but unfortunately it leaves openings for inaccessible code to get into our projects.
To address that, we can shift from tooling at the edges (team members) to tooling at the central source (source code in a shared repository).
By integrating a Continuous Integration (CI) and Continuous Delivery (CD) pipeline to our code repository we can run tests that check for any accessibility issues any time a change is pushed. If we also use the CI/CD tools to automatically deploy our websites, we could also prevent automated deployments if our tests fail.
How awesome is that!?
(This also applies to other types of test: unit, integration, etc but we’re focused on accessibility)
The first thing we’ll want to do is set up automated accessibility testing. Most accessibility testing tools will use some sort of synthetic, or “headless” browsers.
Headless browsers are tools that imitate the rendering behavior of standard browsers without any visual representation. We can use them to “open” our website and the headless browser responds with the same code as a standard browser. You just don’t see anything.
It’s much faster and allows us to write tests against out frontend code. This makes it much easier to test whether markup that SHOULD be on a webpage actually arrives.
Most headless browsers work well enough for enforcing things in the markup, but they generally fall short for things like color contrast.
Cypress is an exception.
Cypress is different because it ships an electron app that can launch an actual browser and automatically drive it through your tests. In addition to watching your tests run, you can tell Cypress to run in headless mode, which is not visible but can still detect the colors on your page.
Cypress itself does not know anything about accessibility though, but there is a plugin called cypress-axe by Deque (notice a pattern?) that can be used check for a11y issues within tests.
With everything hooked up, we can begin adding accessibility tests to our applications. One that checks the homepage might look like this:
describe('Homepage', () => {
it('is accessible', () => {
cy.visit('/');
cy.injectAxe();
cy.checkA11y();
});
});
Note that this test checks the entire page. If you are working with component frameworks, they also offer the ability to test individual components. See the component testing documentation here.
Once we have our tests written, we can trigger the test command from a CI/CD pipeline. Your CI/CD tool may differ, but here is an example for a GitHub Action that runs Cypress tests. Assume the package.json
file contains a script called "test"
that runs the "cypress"
CLI command.
name: Test
on:
pull_request:
branches: [production, staging]
types: ['opened', 'edited', 'reopened', 'synchronize']
jobs:
cypress-run:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v2
- name: Install dependencies
run: npm ci
- name: Run Cypress End-to-End tests headlessly
run: npm run test -- --headless
Here are some more handy links if you need more documentation around this:
The big benefit to doing thing this way is that it completely removes the tooling requirements from individuals. The folks that want to opt in to tooling like editor plugins may do so to get the help while they write. Those that prefer not to not may opt out. But accessibility will be checked regardless.
Closing
I hope you found this article helpful and will take additional steps to make the web a more accessible place. I’ve found these tools to work well for improving accessibility without getting in the way.
However, there is a major caveat I want to reiterate. Tooling and automated tests have gotten really good, but I can’t see a scenario in the near future where it can replace user testing.
Even if your automated tests pass WCAG guidelines 100% it does not always mean your website is accessible. There are many things that cannot be caught automatically.
There’s an interesting article by Manuel Matuzovic called “Building the most inaccessible site possible with a perfect Lighthouse score” that takes a funny look at this. It’s worth reading.
The best advice I can give for that is to gather real data about your users, what devices they are using, and try to provide the best experience possible for everyone.
But if we can use tools created by accessibility experts means more people on the team can find bugs without having to be experts themselves.
Heck, even for the experts, using robots can greatly speed up the process.
Thank you so much for reading. If you liked this article, please share it, and if you want to know when I publish more articles, sign up for my newsletter or follow me on Twitter. Cheers!
Originally published on austingil.com.
Top comments (2)
Austin, thanks for your article.
I'm using tools from the accessibilityinsights.io/en/.
I'm developing for Windows and I'm not sure about Web tools, but for desktop applications it's useful tool.
Awesome. Thanks for sharing. They offer a browser extension which fall well in with the other I shared.