Top 10 WCAG Failures Found on Real Websites (And How to Fix Each One)
These 10 accessibility issues appear on over 90% of websites. Learn what they are, why they matter, and exactly how to fix them — with code examples.
WebAIM's annual analysis of the top 1,000,000 websites consistently finds the same accessibility failures year after year. The 2025 report found an average of 56.8 errors per homepage. And the same 10 issues account for over 90% of all detected failures.
Here they are — with real code to fix each one.
1. Low Contrast Text
WCAG Criterion: 1.4.3 Contrast (Minimum) — Level AA
The #1 most common failure. Found on 81% of homepages. Light gray text on white backgrounds, trendy color schemes that sacrifice readability for aesthetics.
The rule: Normal text needs a contrast ratio of at least 4.5:1. Large text (18px+ bold or 24px+ regular) needs 3:1.
Bad:
<p style="color: #999999;">This text on white has a 2.85:1 ratio.</p>
Fixed:
<p style="color: #595959;">This text on white has a 7:1 ratio.</p>
Quick fix: Use a contrast checker and adjust your color palette. Most of the time, slightly darkening your grays solves it.
2. Missing Alternative Text for Images
WCAG Criterion: 1.1.1 Non-text Content — Level A
Found on 54% of homepages. Every meaningful image needs alt text. Decorative images need an empty alt attribute (alt="").
Bad:
<img src="team-photo.jpg">
<img src="decorative-divider.png">
Fixed:
<img src="team-photo.jpg" alt="The AccessiGuard team at the 2025 a11y conference">
<img src="decorative-divider.png" alt="" role="presentation">
Tips:
- Describe what the image shows, not how it looks
- Don't start with "Image of..." — screen readers already announce it as an image
- Logos should have alt text with the company name
- Background images in CSS don't need alt text (they're inherently decorative)
3. Empty Links
WCAG Criterion: 2.4.4 Link Purpose — Level A
Links with no text content. Usually icon-only links (social media icons, hamburger menus) without accessible names.
Bad:
<a href="https://twitter.com/company">
<i class="fa fa-twitter"></i>
</a>
Fixed:
<a href="https://twitter.com/company" aria-label="Follow us on Twitter">
<i class="fa fa-twitter" aria-hidden="true"></i>
</a>
Rule of thumb: If you removed all CSS and your link is blank, it needs an accessible name.
4. Missing Form Input Labels
WCAG Criterion: 1.3.1 Info and Relationships — Level A
Found on 46% of homepages. Form inputs without associated <label> elements. Placeholder text is NOT a label.
Bad:
<input type="email" placeholder="Enter your email">
Fixed:
<label for="email">Email address</label>
<input type="email" id="email" placeholder="e.g., name@example.com">
If you need a visually hidden label:
<label for="search" class="sr-only">Search the site</label>
<input type="search" id="search" placeholder="Search...">
Why placeholders aren't labels: They disappear when you start typing, and many screen readers don't reliably announce them.
5. Empty Buttons
WCAG Criterion: 4.1.2 Name, Role, Value — Level A
Same problem as empty links, but for buttons. Icon buttons without text.
Bad:
<button><svg><!-- hamburger icon --></svg></button>
Fixed:
<button aria-label="Open navigation menu">
<svg aria-hidden="true"><!-- hamburger icon --></svg>
</button>
6. Missing Document Language
WCAG Criterion: 3.1.1 Language of Page — Level A
Found on 18% of homepages. The <html> element needs a lang attribute.
Bad:
<html>
Fixed:
<html lang="en">
Why it matters: Screen readers use the language to pick the correct pronunciation engine. Without it, a French screen reader might try to read English text with French pronunciation — making it incomprehensible.
7. Inaccessible Navigation / Missing Skip Links
WCAG Criterion: 2.4.1 Bypass Blocks — Level A
Keyboard users have to tab through your entire navigation on every page load. A skip link lets them jump straight to content.
Add this as the first element in your <body>:
<a href="#main-content" class="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:bg-white focus:px-4 focus:py-2 focus:z-50">
Skip to main content
</a>
<!-- ... navigation ... -->
<main id="main-content">
<!-- page content -->
</main>
Test it: press Tab when a page loads. The skip link should appear.
8. Broken ARIA Usage
WCAG Criterion: 4.1.2 Name, Role, Value — Level A
ARIA attributes are powerful but widely misused. The first rule of ARIA: don't use ARIA if native HTML works.
Common mistakes:
<!-- Don't do this -->
<div role="button" onclick="submit()">Submit</div>
<!-- Do this instead -->
<button type="submit">Submit</button>
<!-- Don't do this -->
<div role="navigation">...</div>
<!-- Do this instead -->
<nav>...</nav>
ARIA is a last resort. Native HTML elements have built-in keyboard handling, focus management, and screen reader support. Custom ARIA requires you to implement ALL of that manually.
9. Auto-Playing Media
WCAG Criterion: 1.4.2 Audio Control — Level A
Auto-playing video or audio with no way to pause or mute. Extremely disruptive for screen reader users (the audio fights with their screen reader).
Rules:
- Don't auto-play audio. Ever.
- If you auto-play video, mute it by default
- Always provide visible pause/stop controls
<!-- If you must auto-play video -->
<video autoplay muted loop>
<source src="hero-bg.mp4" type="video/mp4">
</video>
<!-- And provide a pause button -->
<button onclick="toggleVideo()" aria-label="Pause background video">
Pause
</button>
10. Keyboard Traps
WCAG Criterion: 2.1.2 No Keyboard Trap — Level A
Custom modals, dropdowns, and widgets that capture keyboard focus and don't let users Tab out. Once you're in, you can't escape.
Modal must-haves:
// Trap focus WITHIN the modal (not forever)
// Close on Escape key
// Return focus to trigger element when closed
dialog.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
closeModal();
triggerButton.focus(); // Return focus
}
});
Better yet, use the native <dialog> element:
<dialog id="my-modal">
<h2>Modal Title</h2>
<p>Content here.</p>
<button onclick="this.closest('dialog').close()">Close</button>
</dialog>
Native <dialog> handles focus trapping and Escape key automatically.
How to Find These Issues on Your Site
You can catch most of these with automated tools:
- Run a scan — Tools like AccessiGuard detect contrast issues, missing alt text, empty links/buttons, missing labels, language attributes, and ARIA misuse automatically
- Keyboard test — Tab through your entire site. Can you reach everything? Can you always see where focus is? Can you escape every component?
- Screen reader test — Turn on VoiceOver (Mac) or NVDA (Windows) and try to complete a task on your site
Automated scanning catches issues 1-6 and 8 reliably. Issues 7, 9, and 10 often need manual testing.
The Pattern
Notice something? Most of these fixes are simple HTML. Use semantic elements, add labels, write alt text, check contrast. Accessibility isn't about complex engineering — it's about not cutting corners on the basics.
The sites that score well aren't using fancy tooling. They're just writing proper HTML.
Want to see how your site stacks up? Run a free scan on AccessiGuard — it checks for all of the automated issues above in under 60 seconds.