Back to all articles
WCAG

Top 10 Most Common Website Accessibility Mistakes (And How to Fix Them)

Discover the 10 most common WCAG accessibility mistakes found in audits and learn exactly how to fix each one with practical code examples.

EEA Compliance TeamJuly 16, 202512 min read
Share:

The Same Mistakes, Over and Over Again

After reviewing thousands of websites for accessibility compliance, a clear pattern emerges: the same 10 mistakes appear on nearly every site. These aren't obscure edge cases — they're fundamental issues that affect real users every day.

The good news? Most of these mistakes are straightforward to fix. Many require just a few lines of code. This guide walks through each one, explains why it's a problem, and shows you exactly how to fix it.

These issues align with WCAG 2.2 Level AA — the standard referenced by the European Accessibility Act (EAA) through EN 301 549. Fixing them gets you closer to both legal compliance and a better experience for all users.


1. Missing Alternative Text on Images

WCAG Criterion: 1.1.1 Non-text Content (Level A)

This is the single most common accessibility violation on the web. According to the WebAIM Million report, over 54% of homepages have images without alt text.

Why It's a Problem

When an image has no alt attribute, screen readers either skip it entirely or — worse — read out the file name. A user hears "image slash product underscore 4523 dot jpeg" instead of a meaningful description.

How to Fix It

<!-- ❌ Bad: No alt text -->
<img src="/products/blue-jacket.jpg">

<!-- ❌ Bad: Useless alt text -->
<img src="/products/blue-jacket.jpg" alt="image">

<!-- ✅ Good: Descriptive alt text -->
<img src="/products/blue-jacket.jpg" alt="Blue waterproof hiking jacket with hood, front view">

<!-- ✅ Good: Decorative image (empty alt) -->
<img src="/decorations/divider.svg" alt="">

Rules of thumb:

  • If the image conveys information, describe it meaningfully.
  • If the image is purely decorative, use alt="" (empty alt, not missing alt).
  • If the image contains text, include that text in the alt attribute.

2. Insufficient Color Contrast

WCAG Criterion: 1.4.3 Contrast (Minimum) (Level AA)

Low-contrast text is everywhere — light gray text on white backgrounds, pastel buttons with white labels, placeholder text that's nearly invisible.

Why It's a Problem

Approximately 1 in 12 men and 1 in 200 women have some form of color vision deficiency. Low contrast also affects older users, anyone in bright sunlight, and users on low-quality screens. If your text doesn't have enough contrast, people literally can't read it.

How to Fix It

WCAG requires:

  • 4.5:1 contrast ratio for normal text (under 18pt / 24px)
  • 3:1 contrast ratio for large text (18pt+ bold or 24px+ regular)
  • 3:1 for UI components and graphical objects
/* ❌ Bad: Light gray on white — 2.5:1 ratio */
.subtitle {
  color: #aaaaaa;
  background: #ffffff;
}

/* ✅ Good: Dark gray on white — 7.4:1 ratio */
.subtitle {
  color: #505050;
  background: #ffffff;
}

Tools: Use the WebAIM Contrast Checker or browser DevTools (Chrome's accessibility inspector shows contrast ratios on hover) to verify your color combinations.


3. Missing Form Labels

WCAG Criterion: 1.3.1 Info and Relationships (Level A), 4.1.2 Name, Role, Value (Level A)

Forms without proper labels are one of the most damaging accessibility failures — they make it impossible for screen reader users to know what information a field expects.

Why It's a Problem

When a form input has no programmatically associated label, screen readers announce it as "edit text" or "text field" — with no indication of what to type. Users are forced to guess. Placeholder text is not a substitute: it disappears on focus and isn't reliably announced by all assistive technologies.

How to Fix It

<!-- ❌ Bad: No label, only placeholder -->
<input type="email" placeholder="Email address">

<!-- ❌ Bad: Visual label but no association -->
<span>Email address</span>
<input type="email">

<!-- ✅ Good: Properly associated label -->
<label for="email">Email address</label>
<input type="email" id="email">

<!-- ✅ Good: Visually hidden label (when design requires it) -->
<label for="search" class="sr-only">Search</label>
<input type="search" id="search" placeholder="Search...">

The .sr-only class (screen reader only) hides the label visually while keeping it accessible:

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

4. No Keyboard Accessibility

WCAG Criterion: 2.1.1 Keyboard (Level A)

If users can't operate your website using only a keyboard, it's inaccessible to anyone who can't use a mouse — including people with motor disabilities, power users, and screen reader users.

Why It's a Problem

Custom interactive elements built with <div> and <span> tags are invisible to keyboard navigation. Click events on non-semantic elements don't fire on Enter or Space. Users get stuck, can't reach content, or can't activate controls.

How to Fix It

<!-- ❌ Bad: Not keyboard accessible -->
<div class="button" onclick="submitForm()">Submit</div>

<!-- ✅ Good: Use semantic HTML -->
<button type="submit">Submit</button>

<!-- ✅ Acceptable: If you must use a div, add full keyboard support -->
<div
  role="button"
  tabindex="0"
  onclick="submitForm()"
  onkeydown="if(event.key === 'Enter' || event.key === ' ') submitForm()"
>
  Submit
</div>

Best practice: Always prefer semantic HTML elements (<button>, <a>, <input>, <select>) over custom elements with ARIA. They come with keyboard support, focus management, and screen reader compatibility built in.

Test it: Unplug your mouse and try navigating your site using only Tab, Shift+Tab, Enter, Space, Escape, and Arrow keys. Can you reach and operate every interactive element?


5. Missing or Incorrect Heading Structure

WCAG Criterion: 1.3.1 Info and Relationships (Level A)

Headings aren't just visual design elements — they're the primary navigation tool for screen reader users. Many sites use headings purely for styling, skipping levels or using the wrong hierarchy.

Why It's a Problem

Screen reader users often navigate by jumping between headings (the "H" key in most screen readers). If your heading structure is broken — skipping from H1 to H4, using multiple H1s, or using headings just because you want bigger text — this navigation becomes unreliable and confusing.

How to Fix It

<!-- ❌ Bad: Skipped levels, multiple H1s, styled-only headings -->
<h1>My Store</h1>
<h1>Featured Products</h1>
<h4>Running Shoes</h4>
<div class="big-text">On Sale Now</div>

<!-- ✅ Good: Logical hierarchy, no skipped levels -->
<h1>My Store</h1>
  <h2>Featured Products</h2>
    <h3>Running Shoes</h3>
    <h3>Trail Boots</h3>
  <h2>On Sale Now</h2>

Rules:

  • One <h1> per page (usually the page title).
  • Don't skip levels — H2 should follow H1, H3 should follow H2.
  • Never use heading tags just for visual styling. Use CSS instead.
  • Conversely, if text looks like a heading, it should be a heading.

WCAG Criterion: 2.4.4 Link Purpose (Level A)

"Click here," "Read more," "Learn more" — these links are everywhere and they're meaningless out of context.

Why It's a Problem

Screen reader users often pull up a list of all links on a page to navigate quickly. When every link says "click here" or "read more," the list is useless — the user has no idea where each link goes.

How to Fix It

<!-- ❌ Bad: Non-descriptive link text -->
<p>To learn about our return policy, <a href="/returns">click here</a>.</p>

<!-- ❌ Bad: Multiple identical "Read more" links -->
<a href="/blog/post-1">Read more</a>
<a href="/blog/post-2">Read more</a>

<!-- ✅ Good: Descriptive link text -->
<p><a href="/returns">Read our return policy</a></p>

<!-- ✅ Good: Unique, descriptive links -->
<a href="/blog/post-1">Read more about EAA compliance</a>
<a href="/blog/post-2">Read more about WCAG testing</a>

<!-- ✅ Good: Using aria-label when you can't change visible text -->
<a href="/blog/post-1" aria-label="Read more about EAA compliance">Read more</a>

WCAG Criterion: 2.4.1 Bypass Blocks (Level A)

Most websites have extensive navigation menus. Without a skip link, keyboard users must tab through every single navigation item on every page load before reaching the main content.

Why It's a Problem

Imagine tabbing through 30+ menu items every time you visit a new page. For keyboard-only users, this is exhausting and time-consuming. Skip links let users jump directly to the content they came for.

How to Fix It

<!-- Add as the FIRST element inside <body> -->
<a href="#main-content" class="skip-link">Skip to main content</a>

<!-- Navigation goes here -->
<nav>...</nav>

<!-- Main content area with matching ID -->
<main id="main-content">
  ...
</main>
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  padding: 8px 16px;
  background: #000;
  color: #fff;
  z-index: 100;
  transition: top 0.2s;
}

.skip-link:focus {
  top: 0;
}

The skip link is invisible by default and appears when a keyboard user tabs to it as the first focusable element.


8. Inaccessible Modal Dialogs and Pop-ups

WCAG Criterion: 2.1.2 No Keyboard Trap (Level A), 2.4.3 Focus Order (Level A)

Cookie consent banners, newsletter sign-ups, promotional overlays — modals are everywhere in modern websites, and they're almost always inaccessible.

Why It's a Problem

When a modal opens, three things typically go wrong:

  1. Focus isn't moved to the modal — keyboard users keep tabbing through the page behind it.
  2. Focus isn't trapped within the modal — users tab out of the modal into invisible background content.
  3. Focus isn't returned when the modal closes — users lose their place on the page.

How to Fix It

<dialog id="newsletter-modal" aria-labelledby="modal-title">
  <h2 id="modal-title">Subscribe to our newsletter</h2>
  <label for="modal-email">Email address</label>
  <input type="email" id="modal-email">
  <button type="submit">Subscribe</button>
  <button onclick="document.getElementById('newsletter-modal').close()">
    Close
  </button>
</dialog>

Using the native <dialog> element with .showModal() handles focus trapping automatically. If you're using a custom modal, you need to:

  1. Move focus to the modal (or its first focusable element) when it opens.
  2. Trap focus inside the modal — Tab should cycle through modal elements only.
  3. Close on Escape — pressing Escape should dismiss the modal.
  4. Return focus to the element that triggered the modal when it closes.

9. Auto-Playing Media Without Controls

WCAG Criterion: 1.4.2 Audio Control (Level A), 2.2.2 Pause, Stop, Hide (Level A)

Auto-playing videos, background music, and animated carousels that can't be paused are disorienting and disruptive.

Why It's a Problem

  • Auto-playing audio interferes with screen reader output — users can't hear their screen reader over your background music or video.
  • Auto-playing video or animation can trigger seizures in people with photosensitive epilepsy.
  • Carousels that auto-advance don't give users enough time to read the content, violating the WCAG timing requirement.

How to Fix It

<!-- ❌ Bad: Auto-playing video with sound -->
<video autoplay src="promo.mp4"></video>

<!-- ✅ Good: Muted autoplay with visible controls -->
<video autoplay muted controls src="promo.mp4">
  <track kind="captions" src="promo-captions.vtt" srclang="en" label="English">
</video>

<!-- ✅ Good: Carousel with pause control -->
<div role="region" aria-label="Featured promotions" aria-roledescription="carousel">
  <button aria-label="Pause carousel">⏸ Pause</button>
  <!-- slides -->
</div>

Rules:

  • Never auto-play audio. If you must auto-play video, mute it by default.
  • Always provide visible play/pause controls.
  • Carousels must have a pause mechanism. Even better: don't auto-rotate at all.
  • Include captions for all video content.

10. Poor Focus Indicators

WCAG Criterion: 2.4.7 Focus Visible (Level AA), 2.4.11 Focus Not Obscured (Level AA, new in WCAG 2.2)

Many websites remove the default browser focus outline for aesthetic reasons, making it impossible for keyboard users to see where they are on the page.

Why It's a Problem

The focus indicator is the keyboard equivalent of a mouse cursor. Without it, keyboard users are navigating blind — they have no idea which element is currently active. This makes it functionally impossible to use the site without a mouse.

How to Fix It

/* ❌ Bad: Removing focus outline entirely */
*:focus {
  outline: none;
}

/* ✅ Good: Custom focus style that's clearly visible */
*:focus-visible {
  outline: 3px solid #1a73e8;
  outline-offset: 2px;
}

/* ✅ Good: Different style for dark backgrounds */
.dark-section *:focus-visible {
  outline: 3px solid #ffffff;
  outline-offset: 2px;
}

Note the use of :focus-visible instead of :focus. This CSS pseudo-class applies focus styles only when the browser determines the user is navigating via keyboard, so mouse users won't see the outline when clicking. This is the modern best practice — you get clear keyboard focus indicators without affecting mouse interactions.

WCAG 2.2 adds a new criterion (2.4.11 Focus Not Obscured) requiring that focus indicators aren't hidden behind sticky headers, cookie banners, or other overlapping elements. Test by tabbing through your page and verifying the focused element is always visible.


How Many of These Does Your Site Have?

Here's a quick reality check. The WebAIM Million study — which analyzes the top 1,000,000 homepages annually — consistently finds that 96%+ of homepages have detectable WCAG failures. The average page has over 50 errors. Most of those errors fall into the 10 categories above.

The pattern is clear: fix these 10 issues, and you'll eliminate the majority of accessibility barriers on your site.

For a full overview of what WCAG 2.2 requires and how the four principles (Perceivable, Operable, Understandable, Robust) apply, read our WCAG 2.2 beginner's guide.


From Mistakes to Compliance

Fixing these common issues is the fastest path to EAA compliance. Here's how to approach it:

  1. Scan first — Automated tools catch many of these issues instantly. Get a baseline.
  2. Prioritize by impact — Focus on issues that block users from completing tasks (keyboard access, forms, modals).
  3. Fix systematically — Address issues by component (all forms, all images, all headings) rather than page by page.
  4. Test manually — Automated tools miss context-dependent issues. Keyboard and screen reader testing catches what scanners can't.
  5. Monitor continuously — New content and features introduce new accessibility issues. Regular scanning catches regressions.

Curious how accessibility improvements also boost UX and conversions? They go hand in hand.


Find Out What's Broken — In 60 Seconds

Most of the mistakes in this article can be detected automatically. Our free WCAG 2.2 scanner checks your site and tells you exactly which issues to fix — prioritized by severity.

Scan your website for free → No signup required. Get actionable results in under a minute.

Stop guessing. Start fixing.

Share:
EC

EEA Compliance Team

Written by the team at EEA Compliance. We help businesses across Europe achieve and maintain accessibility compliance with automated scanning, actionable insights, and expert guidance.