Fix automated accessibility errorsa reproduction, the fix, and how to know it worked
27 errors the analyzer reports, each with the smallest page that triggers it, the same page fixed, and a way to check the fix that goes past the rule. Each reproduction was run through the analyzer’s engine in Chromium: it fails the rule, and the fix clears it.
WebAIM Million, 2026: share of home pages with each
Errors
27
Groups
6
Checked
Directory
Find your error
Look it up by the analyzer’s rule id, by the axe-core name your other tools print, or by group. Lighthouse runs axe-core, and its accessibility audits use axe’s rule names.
Without an alt attribute, many screen readers read out the file name instead, and what the image was there to say never arrives.
The analyzer reports
Image has no alt attribute — a screen reader will read the file name "sales-march.png" instead.
The fix
Write what the image is for, not what it looks like. A purely decorative image takes an empty alt (alt=""), which tells assistive technology to skip it.
Verify it
Run the analyzer on your page again: image-alt is no longer among the failures.
Read the page with images switched off, or listen to it with a screen reader: each alt should stand in for its image in the sentence around it.
People who are deaf or hard of hearing, and anyone watching with the sound off, get none of the speech and none of the sounds that carry meaning.
The analyzer reports
<video> has no captions track.
The fix
Add a captions track: a WebVTT file with the dialogue and the meaningful sounds, timed to the video.
Verify it
Run the analyzer on your page again: video-caption is no longer among the failures.
Turn the captions on and watch the whole video: every line of speech appears, in time, with the speaker named when it is not obvious. The analyzer sees that a track exists, not what is in it.
In axe-core and LighthouseNeeds review: video-caption
Screen reader users often move through a page by its list of links, where there is no sentence around each one. Ten "Read more" links are ten identical entries.
The analyzer reports
Link text "Read more" does not describe its destination.
The fix
Put the destination in the link text. If the design needs the short words, extend them with visually hidden text.
Verify it
Run the analyzer on your page again: link-name-generic is no longer among the failures.
List every link on the page (a screen reader's links list does this) and read the list alone: no two different destinations share a name.
The placeholder disappears at the first keystroke, so the field forgets what it was for while it is being filled in. It is usually too faint to read as well.
The analyzer reports
Field is labelled only by its placeholder "Email".
The fix
Use a real label that stays. If a placeholder remains, it holds an example of the format, never the name of the field.
The reproduction also fails identify-input-purpose, and the fix clears that too.
Verify it
Run the analyzer on your page again: label-placeholder-only is no longer among the failures.
Type into the field: its name is still on screen. axe-core does not report this one, because a placeholder does give the field an accessible name.
Gray at 2.85:1 on white is hard to read for people with low vision, for older eyes, and for anyone on a phone in daylight.
The analyzer reports
Contrast 2.85:1 is below the required 4.5:1 for normal text (16px). #999999 on #ffffff.
The fix
Darken the text until it reaches 4.5:1, or 3:1 for large text. #767676 is the lightest gray that reaches 4.5:1 on white.
Verify it
Run the analyzer on your page again: color-contrast is no longer among the failures.
Check the pair in the contrast checker, then check hover, focus and visited states, and the dark theme. Text over an image or a gradient needs a person; the rule measures solid colors.
Removing the outline without a replacement leaves keyboard users with no idea where they are on the page.
The analyzer reports
1 rule(s) remove the focus outline without providing a replacement: button:focus { outline: none }
The fix
Style :focus-visible instead of removing the outline: the ring shows for keyboard use and stays out of the way for mouse clicks.
Verify it
Run the analyzer on your page again: focus-visible is no longer among the failures.
Tab through the page: every stop shows a ring you can see at a glance, at 3:1 against the background. axe-core has no rule for this; it takes a person or this analyzer's stylesheet check.
The link is hidden from screen readers but still takes focus, so a keyboard user lands on something that, for their screen reader, does not exist.
The analyzer reports
aria-hidden="true" contains <a> that remain in the tab order.
The fix
Hide it from everyone. inert on the container takes its contents out of the tab order as well; this is the usual fix for the page behind an open dialog. If nobody should see it, use hidden.
Verify it
Run the analyzer on your page again: aria-hidden-focus is no longer among the failures.
Tab through the page: focus never reaches the hidden part.
The page reloads every 30 seconds whatever the reader is doing, so a screen reader starts again from the top and someone reading slowly never finishes.
The analyzer reports
Page refreshes after 30s.
The fix
Remove the timed refresh. Update the part that changes in place, and let the reader pause or ask for the update.
Verify it
Run the analyzer on your page again: meta-refresh is no longer among the failures.
Leave the page open for a few minutes while reading with a screen reader: it is never interrupted.
Each reproduction is the code shown, placed in a page that is otherwise clean: a language, a title, a main landmark and one h1. “Copy the whole page” copies exactly that page.
Both pages of every entry were run through the analyzer’s own engine in Chromium 147.0.7727.15, with axe-core 4.12.1 on the same pages, on 18 October 2026. A reproduction is published only if it fails its rule, and a fix only if it clears that rule without leaving or adding a failure at level A or AA. The messages above are the engine’s own words from that run.
A rule that passes is not the end. Every entry ends with a check a person makes, because the rule confirms the markup and not the experience: the manual testing page puts those checks in order.