1. Why you have to test by hand
Start with the number that decides everything else. Automated accessibility tools find roughly a third of the problems on a page. Different studies land on slightly different figures, but nobody has ever put it near a hundred, and nobody ever will, because most of what goes wrong is a judgement call.
Here is the difference in one line. A tool can tell you an image has no
alt attribute. A tool cannot tell you the alt text says
"image".
| A tool can check | Only a person can check |
|---|---|
Is there an alt attribute |
Does the alt text describe the picture |
| Is this contrast ratio 4.5 to 1 | Can you still tell which button is selected |
Does the page have an h1 |
Does the heading outline match the page |
| Does this field have a label | Does the label say what to type |
Is aria-expanded present |
Does it actually change when you click |
| Is the link text empty | Does "read more" mean anything on its own |
| Nothing about the keyboard order | Can you reach and use every control by keyboard |
The trap to watch for: a Lighthouse accessibility score of 100 means no automated failure was found. It does not mean the page is accessible. A page with a perfect score can still be completely unusable by keyboard. Never put an automated score in a report as though it were a result.
2. The fifteen minute pass
This is the sequence to run on any page, in this order, before you do anything cleverer. The order matters, because each step sets up the next one. Fifteen minutes gets you most of the way on a normal page.
Run an automated scan
Two minutes. axe DevTools or WAVE. Fix or note whatever it finds, then put the tool away. This clears the noise so your own attention goes on the real work.
Unplug the mouse
Five minutes. Tab through the whole page and back again. This finds more real problems than every other step put together.
Zoom to 200 percent
Two minutes. Then narrow the window until it is about 320 pixels wide. Look for anything cut off, overlapping, or forcing sideways scrolling.
Turn on a screen reader
Five minutes. Read the page from the top, then jump by heading, then by landmark, then by form field. Listen for anything unnamed or nonsensical.
Write it down while it is fresh
One minute per finding. What, where, who it affects, which success criterion, and how to reproduce it. Section 9 has the template.
If you only ever do step 2, you are already ahead of most teams. If you can only add one more, add step 4.
3. Testing with a keyboard
Put the mouse out of reach. Not to one side, out of reach, because the habit is stronger than the intention. Then put your cursor in the address bar, press Tab, and start walking.
The keys, and what each one should do
| Key | What should happen |
|---|---|
| Tab | Move forward to the next control. Only controls, not plain text. |
| Shift + Tab | Move back. The reverse order should mirror the forward one exactly. |
| Enter | Follow a link. Press a button. Submit a form from a text field. |
| Space | Press a button. Tick a checkbox. Scroll the page when nothing is focused. |
| Arrow keys | Move inside a group: radio buttons, a tab set, a menu, a slider, a select. |
| Esc | Close the dialog, the menu or the autocomplete list, and put focus back where it came from. |
| Home / End | Jump to the first or last item inside a group such as a tab set or a menu. |
The Space and Enter rule: a native
<button> responds to both. A native <a href>
responds to Enter only. If someone has built a link that behaves like a button, or a
<div> pretending to be either, this is where it falls apart. Try both
keys on every control that looks like a button.
The seven questions to ask as you Tab
- Can I see where I am, at every single stop? If the focus indicator vanishes even once, that is a finding. This is the most common failure there is.
- Can I reach everything? Every link, button, field, tab, menu item and custom control. If you can click it with a mouse, you must be able to reach it with Tab.
- Does the order make sense? It should follow the visual reading order. If focus jumps from the top of the page to the footer and back up, someone has moved things around with CSS.
- Can I get out of everything I got into? Tab into a widget, then Tab out. If you cannot, that is a keyboard trap, and it can end the session for a keyboard user.
- Does Escape work where it should? Open every dialog, menu and autocomplete and try to close it with Escape.
- Where does focus land after something happens? Open a dialog, focus should move into it. Close the dialog, focus should return to the button that opened it. Delete a row, focus should go somewhere sensible rather than to the top of the page.
- Is there a skip link? Press Tab once on a fresh page load. The first thing should usually be a link that jumps past the navigation.
Things that look fine and are not
- Focus is technically there but invisible. Someone set
outline: noneand put nothing back. Look carefully at low contrast elements, and at controls sitting on a coloured background. - A control that only responds to a click. Very common on
<div>and<span>elements with a click handler. You will notice because pressing Enter does nothing at all. - A menu that opens on hover only. There is no hover on a keyboard, and none on a touchscreen either.
- A modal that lets you Tab behind it. Open the dialog, then keep pressing Tab. If the page underneath starts taking focus, the dialog is not modal in any way that matters.
- An off screen menu that is still tabbable. The menu is hidden with
transformor a negative position rather thandisplay: none, so focus disappears into a panel you cannot see.
4. Testing with a screen reader
This is the step people skip, because the first ten minutes are genuinely disorientating. Push through that. You do not need to become a proficient user. You need about eight keystrokes, and those eight will find real problems within minutes.
Use the right pairing. Screen readers and browsers are tested together, so use NVDA with Firefox or Chrome, VoiceOver with Safari, and TalkBack with Chrome. Testing NVDA in Safari will produce problems that no real user has.
NVDA on Windows, which is free
The NVDA key is Insert by default, and Caps Lock if you choose the laptop layout during setup. It is written as NVDA below.
| Key | What it does |
|---|---|
| Ctrl | Stop talking. Learn this one first, before anything else. |
| NVDA + Q | Quit NVDA. |
| NVDA + ↓ | Read continuously from here down. On the laptop layout this one is NVDA + A instead. |
| H / Shift+H | Next and previous heading. Press 1 to 6 for a specific level. |
| D | Next landmark. This is how you check your banner, nav, main and footer exist. |
| K | Next link. |
| F | Next form field. |
| B | Next button. |
| T / L | Next table, next list. |
| NVDA + F7 | The elements list. Every heading, link and landmark on the page in one dialog. Enormously useful. |
| NVDA + Space | Switch between browse mode and focus mode. See below. |
Browse mode and focus mode: the thing that confuses every beginner. In browse mode, single letters are navigation shortcuts, so pressing H jumps to a heading. In focus mode, those letters are typed into the page. NVDA usually switches to focus mode on its own when you Tab into a text field, and back out when you leave. If your keystrokes suddenly stop working, you are in focus mode. Press NVDA + Space.
VoiceOver on a Mac, which is already installed
The VoiceOver keys are Control + Option, written as VO below. Use it with Safari.
| Key | What it does |
|---|---|
| Cmd + F5 | Turn VoiceOver on and off. |
| Control | Stop talking. |
| VO + → / ← | Move to the next or previous item. |
| VO + A | Read continuously from here. |
| VO + Space | Activate whatever you are on. |
| VO + U | Open the rotor. Then ← and → switch between headings, links, landmarks and form controls, ↑ and ↓ move through the list, and Enter jumps there. |
| VO + Cmd + H | Next heading. |
| VO + Cmd + L | Next link. |
One Safari setting to change first. Turn on Preferences, Advanced, "Press Tab to highlight each item on a webpage". Without it Safari skips links when you Tab, and you will report keyboard problems that are really browser settings.
The eight things to listen for
- Does every control have a name? If you hear "button" or "link" with nothing before it, that control is anonymous. Icon only buttons are the usual offenders.
- Do the images say something useful? Listen for a file name, the word "image", or a long stream of nonsense.
- Does the heading list make sense on its own? Pull up the elements list or the rotor and read only the headings. It should read like a table of contents.
- Does the link list make sense on its own? Same trick. Nine links all called "read more" is a finding.
- Are the landmarks there? Press D a few times. You should hear banner, navigation, main and content information.
- Do the form fields say what to type? Tab into each one. You should hear the label, the type of field, whether it is required, and any error.
- Are the states announced? Open a menu. You should hear "expanded". Tick a checkbox. You should hear "checked".
- Is anything announced that should not be? Decorative images, empty elements and repeated icon labels all add noise nobody needs.
5. Zoom, reflow and text spacing
Three separate checks that people tend to blur into one. They test different things and they break for different reasons.
Zoom to 200 percent
Press Ctrl or Cmd with + until the browser says 200 percent. This is the plain magnification check. Nothing should be cut off, nothing should overlap, and nothing should need sideways scrolling to read.
Reflow at 320 pixels
This is the harder one. WCAG asks that content works in a window 320 CSS pixels wide without a horizontal scrollbar. You can get there two ways. Narrow the browser window until it is about 320 pixels, or zoom a 1280 pixel wide window to 400 percent, which comes to the same thing.
What usually breaks here is a fixed width, a wide table, or a long unbroken string such as a URL or a line of code. Tables and code blocks are allowed to scroll inside their own box. The page is not allowed to scroll sideways. That distinction is the whole criterion.
Text spacing
Some readers increase spacing to make text easier to follow. WCAG says your layout has to survive it. The four values to apply are:
The four text spacing values
Line height at least 1.5 × the font size
Space after a paragraph at least 2 × the font size
Letter spacing at least 0.12 × the font size
Word spacing at least 0.16 × the font size
Apply all four at once, then look for text that has been clipped or hidden. Buttons with a fixed height are the usual casualty. Nothing may be lost, though the layout is allowed to get taller.
Reading the four values does not tell you much. Watching them land does. Both cards below hold exactly the same words, and at rest they look the same. The one marked fixed height sets a height on the card and on the button, the way a great deal of real code does. The one marked minimum height sets a floor instead and lets the box grow. Tick the box to apply the four values to both.
Line height 1.5, paragraph spacing 2em, letter spacing 0.12em, word spacing 0.16em. Exactly what WCAG 1.4.12 asks for, nothing more.
✕ Fixed height
Booking confirmed
Your appointment is at 2pm on Thursday with Dr Nashid at the Malé clinic.
Add this to my calendar✓ Minimum height
Booking confirmed
Your appointment is at 2pm on Thursday with Dr Nashid at the Malé clinic.
Add this to my calendarThe button in the fixed height card gets sliced in half by the edge of the box. Not scrolled, not hidden behind anything you could reach. Cut off, with the bottom of the label simply not painted, and that is the failure the criterion is written for. The minimum height card gets taller instead, which is allowed and is the correct answer. Growing is fine. Losing half a button is not.
Notice the words not used: neither card is described here as the one on the left or the one on the right, because they sit side by side on a wide screen and stack on a narrow one. Referring to position is the same mistake as "click the green button", and it is worth catching in your own writing.
6. Colour, contrast and motion
The contrast numbers have their own page with a live checker, so this section is only about how to test rather than what the thresholds are. Three quick checks.
- Turn the page to greyscale. Then look for anything you can no longer tell apart. A required field marked only in red, a chart with a colour key and no labels, a selected tab that is only a different shade. If it disappears in greyscale, colour was doing the work on its own.
- Check the things that are not text. People check body text and stop. The border of an input, the icon inside a button, the line on a chart and the focus indicator all need to be visible too, at 3 to 1 against what is behind them.
- Turn on reduced motion and reload. On a Mac it is System Settings, Accessibility, Display, Reduce motion. On Windows it is Settings, Accessibility, Visual effects, Animation effects. Parallax, auto sliding carousels and long transitions should all calm down or stop.
While you are there, look for anything that moves, flashes or plays for more than five seconds without a way to pause it. Motion that starts on its own and cannot be stopped is a failure regardless of how tasteful it is.
7. Automated tools, and what they miss
Use them. They are fast, free and they catch the boring things reliably. Just know what you are holding.
| Tool | Best for | Watch out for |
|---|---|---|
| axe DevTools | The most trustworthy first pass. Very few false positives, and it explains each issue clearly. | It deliberately stays quiet where it is unsure, so a clean result is not an all clear. |
| WAVE | Draws its findings onto the page itself, which makes it the easiest way to show a colleague what is wrong. | Its alerts are prompts to look, not confirmed failures. Read them as questions. |
| Lighthouse | Already in Chrome, and useful for tracking a whole site over time. | The score. See the warning in section 1. |
| The browser's own inspector | Showing you the accessibility tree, so you can see the name and role a control really has. | Nothing. This is the most underused tool on the list. |
One habit worth building. When a control seems wrong, open the browser inspector, find the accessibility pane, and read the computed name and role. That is exactly what a screen reader will say. It turns an argument about what the code ought to do into a fact about what it does.
Scan more than one page: a tool checks one page at a time, and most sites repeat the same component everywhere. Test one of each kind of page, which usually means the home page, a listing, a detail page, a form and a search result. Fixing the shared component fixes it everywhere at once.
8. Testing on a phone
Most people will meet your site on a phone, and a phone screen reader works by gesture rather than by key. It is worth half an hour to learn.
| Gesture | What it does |
|---|---|
| Swipe right | Move to the next item. |
| Swipe left | Move to the previous item. |
| Double tap | Activate whatever is selected. A single tap only selects. |
| Two finger swipe down | Read from here to the end of the screen. |
| Scroll the page | This is the one gesture that differs. Three fingers on iPhone, two fingers on Android. |
| Rotor, or reading controls | Change what a swipe moves by, so you can jump heading to heading. On iPhone, rotate two fingers. On Android, swipe up or down to change the setting. |
Turn VoiceOver on from Settings, Accessibility, VoiceOver. Turn TalkBack on from Settings, Accessibility, TalkBack. Set up the accessibility shortcut while you are there, because turning a screen reader off again with the screen reader running is a memorable first experience.
Three checks that only show up on a real device:
- Tap targets. Anything you struggle to hit with a thumb is too small. WCAG 2.2 asks for at least 24 by 24 pixels, and around 44 by 44 is far more comfortable.
- Rotation. Turn the phone sideways. The page must work in both orientations unless there is a genuine reason it cannot, such as a piano app.
- Pinch zoom. Try to zoom in. If it refuses, someone has set
user-scalable=noin the viewport meta tag. Delete it.
9. Writing a finding up
A finding that nobody can act on is a finding nobody will act on. The same rule applies here as on a building site. Never write "not accessible" on its own. Write what you did, what happened, and what should have happened instead.
| Field | Why it earns its place |
|---|---|
| Where | Page URL and the name of the component. "The filter panel on the search results page." |
| What happens | The observed behaviour, in plain words. Not the diagnosis. |
| How to reproduce | The exact steps, plus the browser and assistive technology you used. |
| Who it affects | Keyboard users, screen reader users, low vision users. This is what makes it real to a reader. |
| Which criterion | The WCAG number and name. It turns an opinion into a requirement. |
| Suggested fix | One concrete option. You are not obliged to design the solution, but a suggestion doubles the chance it gets done. |
✕ Not useful
"The filter dropdown is not accessible. Please fix."
Nobody knows what is wrong, who is affected, or when it is done. This will sit in a backlog until someone closes it.
✓ Actionable
Where. Filter dropdown, search results page.
What happens. The dropdown opens on click but cannot be opened from the keyboard, and Tab moves straight past it to the sort control.
Reproduce. Chrome 130 on Windows, no mouse. Tab from the search box. Focus never lands on the filter button.
Who. Keyboard users, screen reader users and anyone using voice control. They cannot filter results at all.
Criterion. WCAG 2.1.1 Keyboard, level A.
Suggested fix. The trigger is a
<div>. Make it a <button> and it becomes
focusable and operable for free.
Severity, so the list can be ordered
Give every finding one of three levels. Teams argue about five level scales and never argue about three.
- Blocker. Someone cannot complete the task at all. A checkout that cannot be reached by keyboard. A form field with no label. These get fixed first, always.
- Serious. The task is possible but painful or confusing. Poor contrast on body text, a heading order that makes no sense, an unlabelled icon in a place with context around it.
- Minor. Annoying rather than blocking. A decorative image that gets announced, a redundant link title.
One more habit that changes how a report is received. Alongside the failures, note two or three things the team already got right. It is honest, it is useful, and a report that is only bad news tends to get read once and filed.
10. A test record sheet
Print this and fill one in per page you test. It is the digital twin of the field sheet on the measuring page, and it exists for the same reason. Notes made at the time beat memory made later, every time.
Page name and URL
Date
Tester
Browser and version
Screen reader and version
| Check | A pass looks like | Result | Note |
|---|---|---|---|
| Automated scan | Zero errors from axe or WAVERecord the tool and version | ||
| Skip link | First Tab reveals a link past the navFresh page load | ||
| Focus always visible | Every stop, clearlyWatch the low contrast areas | ||
| Everything reachable | Every control takes focusCompare against a mouse pass | ||
| Focus order | Matches the visual order both waysTab, then Shift Tab back | ||
| No keyboard trap | You can Tab out of everythingWidgets and embeds especially | ||
| Dialogs | Focus in, Escape closes, focus returnsTest every dialog | ||
| Headings | One h1, no skipped levels, reads as an outlineElements list or rotor | ||
| Landmarks | Banner, navigation, main, contentinfoPress D in NVDA | ||
| Control names | Nothing announced as a bare "button" or "link"Icon buttons especially | ||
| Images | Useful alt, decorative ones silentListen for file names | ||
| Forms | Label, type, required state and errors all spokenSubmit an empty form | ||
| Link text | Each link makes sense aloneRead the link list only | ||
| Zoom 200% | Nothing clipped or overlappingBrowser zoom | ||
| Reflow at 320px | No sideways page scrollTables may scroll, the page may not | ||
| Text spacing | Nothing cut off with all four values applied1.5, 2, 0.12, 0.16 | ||
| Colour alone | Everything still distinguishable in greyscaleErrors, charts, selected states | ||
| Contrast | 4.5:1 text, 3:1 large text and controlsCheck non text too | ||
| Motion | Reduced motion honoured, nothing unstoppableTurn the OS setting on | ||
| On a phone | Swipe navigation works, targets big enough, pinch zoom allowedReal device |
Findings, with severity, and the two or three things this page already gets right
That completes the four part set. Go back to part 1 on the core concepts, part 2 on the standards or part 3 on measuring a building. The developer page has the code to fix most of what you will find here, the glossary explains any word above, and the resources page has every tool mentioned.