How to test for accessibility
No single method finds every barrier. Automated tools are fast and tireless, but they can only check rules a machine can evaluate — by most counts they catch perhaps a third of WCAG issues. The rest are judgement calls: is this alt text actually meaningful, does the focus order make sense, is the error message understandable, can you complete the task with a keyboard alone? Those need a human. The good news is you don't need a lab or a specialist to start. The four methods below — automated scans, keyboard testing, a screen reader pass, and a zoom-and-contrast check — are cheap to learn, and run together they surface the large majority of real problems.
Test early and often. A barrier caught while you're building a component costs minutes to fix; the same barrier caught in an audit after launch can mean a rebuild. Treat the checks here as part of your normal definition of done, not a separate phase.
Run a scan
Beyond the manual checks below, EqualWeb’s accessibility checker (opens in a new tab) scans a live page and lists issues by WCAG criterion — a fast first pass before you test by hand.
Automated checks
Automated testing tools parse the rendered page and flag patterns that are reliably
wrong: an image with no alt attribute, a form control with no
accessible name, text whose colour contrast falls below the threshold, an
id used twice, ARIA attributes that aren't allowed on their element,
or a heading level that's skipped. They are excellent at exactly this — high-volume,
rule-based checks that a person would be slow and inconsistent at.
The common tools all share the same open-source engine family, so their core results are comparable:
- axe DevTools — a browser extension (and the
axe-corelibrary underneath) that scans the current page and groups issues by severity with a pointer to each element and a fix. - Lighthouse — built into Chrome DevTools; its Accessibility category runs a subset of axe rules and gives a score. Useful as a quick signal, but the score is not a conformance measure.
- WAVE — a visual tool from WebAIM that overlays icons on the page so you can see errors, alerts, and structure in context.
- IBM Equal Access, ARC Toolkit, and others — similar engines with different reporting.
What they reliably cannot tell you: whether alt text is meaningful (only whether it exists), whether the reading and focus order is logical, whether a custom widget actually works with a keyboard, whether an error is announced, whether a link named "read more" makes sense out of context, or whether content still works at 400% zoom. A page can pass every automated rule and still be unusable.
Wire a scan into your pipeline so regressions are caught automatically. Tools like
axe-core, jest-axe, @axe-core/playwright, or
pa11y-ci run in CI and fail the build on new violations — the same way
you'd run unit tests or a linter.
A clean automated scan is not a pass
Automated tools verify only the roughly one-third of WCAG success criteria that can be machine-checked, and even then only for presence, not quality. "Zero violations" means you've cleared the easy, mechanical failures — it tells you nothing about whether a real person can use the page. Always follow a scan with the manual checks below before you call something accessible.
Keyboard testing
This is the highest-value manual test you can run, and it costs nothing: unplug your mouse (or just put it aside) and operate the whole page with the keyboard alone. Many people navigate this way all the time — including screen reader users, people with motor disabilities, and anyone using a keyboard for speed — so if it can't be done with a keyboard, it can't be done at all.
Press Tab to move forward through interactive elements, Shift + Tab to move back, and operate each control as you reach it. Start at the very top of the page and work through every link, button, field, menu, tab, dialog, and custom widget. As you go, watch for these things:
| Key | What to check |
|---|---|
| Tab / Shift+Tab | Every interactive element is reachable and you can move both forward and backward. Focus never lands on a non-interactive element, and never gets stuck (no keyboard trap — you can always tab out, SC 2.1.2). |
| Focus indicator | The element with focus is always clearly visible — a ring or outline you can
see at a glance, with enough contrast (SC 2.4.7). Never outline: none
without a replacement. |
| Order | Focus moves in a logical sequence that matches the visual reading order, not jumping around the page (SC 2.4.3). |
| Enter | Activates links and buttons. Submits the form from a text field where expected. |
| Space | Activates buttons; toggles checkboxes; selects the focused radio. Should not scroll the page while focus is on a control. |
| Arrow keys | Move within composite widgets — radio groups, tabs, menus, selects, sliders, and listboxes — as the ARIA pattern expects. |
| Skip link | The first Tab reveals a "Skip to main content" link, and activating it moves focus past the header into the main region. |
| Esc | Closes the open menu, dialog, or popover and returns focus to the control that opened it. |
A quick way to confirm focus order is to keep an eye on the address-bar status or use
the browser's "show focus" overlay; if you ever lose track of where focus is, that's a
failure in itself. Pay special attention to anything custom — a div styled
to look like a button is the classic thing that looks fine but does nothing on
Enter.
Screen reader testing
A screen reader announces the page aloud, so testing with one tells you what blind and low-vision users actually experience: whether every control has a sensible name, the right role, and announces its state and any changes. You don't need to be a daily user to get value — learning the handful of commands below is enough to catch the most common defects. Screen readers are tightly paired with particular browsers, so test the combinations people really use:
- NVDA with Firefox or Chrome on Windows — free, open source, and the most common pairing to test first.
- VoiceOver with Safari on macOS and iOS — built in; turn it on with Cmd + F5 (or triple-click the side button on iOS).
- JAWS with Chrome on Windows — widely used in enterprise; worth a pass if your audience includes it.
- TalkBack on Android and Narrator on Windows — test these for mobile and built-in coverage.
Screen reader users rarely read top to bottom; they jump around using the page's structure. Learn to do the same — in NVDA and VoiceOver you can move by:
- Headings (NVDA: H; VoiceOver: rotor → Headings) to scan the outline. Confirm the headings describe the content and form a sensible hierarchy.
- Landmarks / regions to jump between banner, navigation, main, and
footer. Confirm the main content is in a
mainlandmark. - Links and form fields to list them out of context. Confirm each link and field name makes sense on its own.
As you move, listen for the three things ARIA exists to convey: the name (does the button say what it does?), the role (is it announced as a button, link, checkbox, tab?), and the state and value (expanded or collapsed, checked, selected, "3 of 5"). Then exercise the page: submit a form with errors and confirm the failure is announced, open a dialog and confirm focus moves into it and its name is read, toggle a control and confirm the new state is spoken. Anything you see on screen but don't hear announced is a barrier.
Zoom, reflow & contrast
People with low vision enlarge pages, override colours, and reduce motion. These checks take a couple of minutes in any browser and catch failures the other methods miss.
- Zoom to 200%. Use Ctrl/Cmd + +. All text must enlarge and stay readable with no clipping or overlap (SC 1.4.4).
- Reflow at 400% (320 CSS pixels). Zoom to 400% in a 1280 px-wide window — equivalent to a 320 px viewport. Content must reflow into a single column with no loss of information or function and no two-dimensional scrolling: you should never have to scroll horizontally to read a line of text (SC 1.4.10 Reflow).
- Colour contrast. Check that body text meets 4.5:1 and large text 3:1 (SC 1.4.3), and that UI components and meaningful graphics meet 3:1 against their background (SC 1.4.11). Use the contrast readout in DevTools, axe, or a dedicated contrast checker.
- Forced colours / High Contrast. Turn on Windows Contrast Themes
(or emulate
forced-colors: activein DevTools). Confirm nothing disappears — borders, focus rings, and icons that rely on background images often vanish unless you account for them. - Reduced motion. Enable "reduce motion" in the OS (or emulate
prefers-reduced-motion: reduce). Confirm large or auto-playing animations are paused or toned down so they don't trigger discomfort (SC 2.3.3).
A manual smoke-test checklist
When you don't have time for a full audit, this ten-minute pass catches the failures that affect the most people. Run it on any page before you ship.
- Images. Every meaningful image has an
altthat conveys its purpose; decorative images have emptyalt="". - Labels. Every form input, select, and textarea has a real,
associated
<label>— click the label and focus should move into the field. - Heading outline. The headings, read in order, form a sensible
outline with no skipped levels, and there is exactly one
<h1>. - Landmarks. The page has
header,nav,main, andfooterlandmarks, and the main content sits in a singlemain. - Colour isn't the only signal. Required fields, errors, links in text, and chart series are distinguishable without relying on colour alone (a label, icon, or underline as well).
- Visible focus. Tab through the page; the focused element is always clearly outlined.
- Forms announce errors. Submit with bad data; each error is tied to its field and announced, not shown only in red.
- Zoom to 400%. Content reflows to one column with no clipping and no horizontal scrolling.
Found something? Learn the fix
Testing tells you what is broken; the Learn lessons show you how to fix it. Each lesson takes a common failure — unlabelled inputs, errors that aren't announced, missing landmarks, low contrast — and walks through a bad example, a good one, and the code to get there. Pair this guide with those lessons and testing becomes a fast loop: find it, fix it, retest.