The 10 WCAG 2.1 AA Failures I See on Almost Every Site (With the Fix for Each)
I have run a lot of accessibility audits in the last two years. First with a CLI I built on top of axe-core, then with Alfa Audit, which is the same engine wrapped in a product so people who are not developers can use it.
The surprising part is not that sites fail. The WebAIM Million study says 94.8% of home pages fail WCAG 2 somewhere. The surprising part is how boring the failures are. WebAIM found that six recurring issues account for 96% of all errors. My own audit logs agree. It's the same ten things, over and over, on a Shopify theme and on a hand-built Next.js app alike.
So here they are, ranked roughly by how often I see them, with three things for each: what it means for a real person, the WCAG criterion a regulator would quote, and the fix.
1. Text with too little contrast
Who it hurts: anyone with low vision, anyone over 45, anyone reading on a phone in sunlight. WebAIM found low-contrast text on 79% of home pages. It is the single most common failure on the web.
Criterion: 1.4.3 Contrast (Minimum). Normal text needs a contrast ratio of at least 4.5:1 against its background; large text (roughly 24px, or 19px bold) needs 3:1.
Fix: stop using light grey on white for "secondary" text. #767676 on white is the darkest grey that passes for normal text; most design systems ship something lighter. Check your muted-foreground token. In Tailwind-style setups this is usually one CSS variable, so the fix is one line that improves the whole site.
/* before: fails at ~3.9:1 */
--muted-foreground: #8a8a8a;
/* after: passes at 4.5:1 */
--muted-foreground: #6b6b6b;
2. Images without alt text
Who it hurts: screen-reader users hear "image" or the file name, IMG_4821.jpg, instead of what the picture shows. More than half of the images WebAIM found had no usable alternative text.
Criterion: 1.1.1 Non-text Content.
Fix: every <img> needs an alt attribute. If the image carries meaning, describe it. If it is decorative, use an empty alt="" so screen readers skip it. The attribute being missing is the failure; empty is fine.
<img src="/team.jpg" alt="The four of us at the Stockholm office, 2025" />
<img src="/divider.svg" alt="" />
Product images deserve real descriptions. "Red wool sweater, crew neck, front view" is useful. "Product image" is not.
3. Form fields without labels
Who it hurts: screen-reader users land on a text box and hear "edit text" with no idea what goes in it. Voice-control users cannot say "click Email" because nothing is called Email.
Criterion: 1.3.1 Info and Relationships and 4.1.2 Name, Role, Value.
Fix: a <label> with a for attribute pointing at the input's id. Placeholder text is not a label; it disappears when you type and most screen readers don't announce it as a name.
<label for="email">Email address</label>
<input id="email" type="email" autocomplete="email" />
If the design really has no visible label, use aria-label="Email address" on the input. Visible labels are better.
4. Empty links and buttons
Who it hurts: a screen reader reads a link by its text. An icon-only link with no text is announced as "link" and nothing else. Over a third of the pages WebAIM scanned had at least one of these. Social icons in the footer are the classic case.
Criterion: 2.4.4 Link Purpose and 4.1.2 Name, Role, Value.
Fix: give it an accessible name.
<a href="https://linkedin.com/in/you" aria-label="Nikola on LinkedIn">
<svg aria-hidden="true">…</svg>
</a>
Same for buttons: a <button> containing only an SVG needs aria-label or visually hidden text.
5. Missing page language
Who it hurts: screen readers pick a voice and pronunciation rules from the page language. Without it, Swedish text gets read with English phonetics, which is somewhere between funny and unusable.
Criterion: 3.1.1 Language of Page.
Fix: one attribute on the root element. This is the cheapest fix on the list and I still see it missing on about a fifth of sites.
<html lang="sv">
6. Headings out of order (or no h1)
Who it hurts: screen-reader users navigate by headings the way sighted users skim. Jumping from an h1 to an h4 because the h4 "looked right" breaks the outline.
Criterion: technically a best practice under 1.3.1 rather than a hard failure, but it shows up in every automated report and regulators read those reports.
Fix: one h1 per page, then h2 for sections, h3 inside those. Style with CSS, not by picking a heading level for its font size.
7. Zoom disabled on mobile
Who it hurts: anyone who needs to pinch-zoom. Which is a lot of people over 50.
Criterion: 1.4.4 Resize Text.
Fix: delete user-scalable=no and any maximum-scale below 5 from your viewport meta tag. Some templates still ship this "to prevent the iOS zoom on input focus." Use font-size: 16px on inputs instead; that is what actually stops the zoom.
<meta name="viewport" content="width=device-width, initial-scale=1" />
8. Keyboard traps and invisible focus
Who it hurts: people who cannot use a mouse. If you Tab through your site and cannot see where you are, or you get stuck inside a modal, they are stuck too.
Criterion: 2.1.2 No Keyboard Trap and 2.4.7 Focus Visible.
Fix: never set outline: none without a replacement. Use :focus-visible so mouse users don't see rings but keyboard users do. Modals need to trap focus inside while open and return it when closed; if you use a component library (Radix, Base UI, Headless UI) this is handled for you, which is a good reason to use one.
:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
9. Iframes without a title
Who it hurts: an embedded map or video is announced as "frame" with no clue what is inside.
Criterion: 4.1.2 Name, Role, Value.
Fix: title="Map of the Stockholm office" on the <iframe>. Thirty seconds.
10. Link text that says "click here"
Who it hurts: screen-reader users often pull up a list of all links on the page. A list of twelve "Read more" entries is useless.
Criterion: 2.4.4 Link Purpose (In Context).
Fix: make the link text say where it goes. "Read the EAA guide" instead of "Read more." If the design insists on a generic label, add an aria-label with the full purpose.
Why automated tools catch all of these
Every item above is detectable from the HTML and the computed styles. That is why an automated audit is the right first step: it finds the things that are both common and mechanical. axe-core, the engine under Alfa Audit and most serious tools, is conservative on purpose: it only reports what it can prove, which is why its reports have very few false positives.
What it cannot tell you is whether your alt text is good, whether the keyboard flow makes sense, or whether your PDFs are tagged. That is the manual part, and it comes after you have cleared the list above. A site with these ten fixed is usually most of the way to WCAG 2.1 AA.
What a to-do list looks like
This is the shape of report I think people actually need, and the shape Alfa Audit produces: not "347 violations," but a ranked list where each row has a severity, the WCAG criterion, the affected elements, and the fix. The first five rows on most sites are items 1 to 5 above. Fix those, re-run, and the score moves.
If you want to see your own list, run a free audit on Alfa Audit. If you want me to look at it with you, sign in to the Inner Circle and ask for a compliance consultation.
The percentages in this post come from the WebAIM Million 2025 study of the top one million home pages. The criterion numbers are WCAG 2.1; they are unchanged in 2.2.



