Skip to main content
Back to Blog
How-To Guides
8 min read

How to Fix the 10 Most Common Accessibility Issues

Step-by-step guide to fixing the most common WCAG violations. Includes code examples and real-world solutions.

By AccessAudit Team

How to Fix the 10 Most Common Accessibility Issues

After analyzing 10,000+ websites with AccessAudit, we've identified the accessibility issues that appear most frequently.

The good news? Most of them take less than 5 minutes to fix.

Here's your practical guide to fixing the top 10 issues we see every day.

1. Missing Image Alt Text (Found on 87% of Sites)

The Problem

Screen readers can't describe images without alt text. Users miss important visual information.

How to Identify

<!-- Problem -->
<img src="product.jpg">
<img src="logo.png">

The Fix

<!-- Solution -->
<img src="product.jpg" alt="Blue running shoes with white laces">
<img src="logo.png" alt="AccessAudit">

<!-- For decorative images -->
<img src="divider.png" alt="">

Decision Tree for Alt Text

  • Is it decorative? → Use alt=""
  • Is it a link? → Describe the destination
  • Is it informative? → Describe what it shows
  • Is it functional? → Describe what it does
  • Is it complex? → Use alt + long description

Time to Fix

⏱️ 2 minutes per image


2. Poor Color Contrast (Found on 73% of Sites)

The Problem

Low contrast makes text unreadable for users with visual impairments or in bright sunlight.

WCAG Requirements

  • Normal text (< 18pt): 4.5:1 contrast ratio
  • Large text (≥ 18pt): 3:1 contrast ratio
  • UI components: 3:1 contrast ratio

Common Failures

/* ❌ Fails - 2.8:1 ratio */
.text { color: #999; background: #fff; }

/* ❌ Fails - 2.1:1 ratio */
.link { color: #6CB4EE; background: #fff; }

/* ❌ Fails - 1.9:1 ratio */
.button { color: #ccc; background: #fff; }

The Fix

/* ✓ Passes - 5.7:1 ratio */
.text { color: #666; background: #fff; }

/* ✓ Passes - 4.5:1 ratio */
.link { color: #0066CC; background: #fff; }

/* ✓ Passes - 4.6:1 ratio */
.button { color: #767676; background: #fff; }

Quick Tools

  • Chrome DevTools (Inspect → Accessibility pane)
  • AccessAudit automated scanner
  • WebAIM Contrast Checker

Time to Fix

⏱️ 5 minutes to update your CSS variables


3. Missing Form Labels (Found on 59% of Sites)

The Problem

Screen readers can't announce what each field is for without proper labels.

How to Identify

<!-- ❌ Problem - Placeholder is not a label -->
<input type="email" placeholder="Email">

<!-- ❌ Problem - Visual label but not associated -->
<span>Password</span>
<input type="password">

The Fix

<!-- ✓ Solution 1: Visible label -->
<label for="email">Email Address</label>
<input type="email" id="email" placeholder="you@example.com">

<!-- ✓ Solution 2: Wrapped label -->
<label>
  Password
  <input type="password">
</label>

<!-- ✓ Solution 3: Visually hidden label (if design requires) -->
<label for="search" class="sr-only">Search</label>
<input type="text" id="search" placeholder="Search...">

CSS for Screen-Reader-Only Text

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

Time to Fix

⏱️ 3 minutes per form


4. Empty Links (Found on 64% of Sites)

The Problem

Links with no text content are announced as "link" with no context.

How to Identify

<!-- ❌ Problem - Icon-only links -->
<a href="/cart">
  <i class="icon-cart"></i>
</a>

<!-- ❌ Problem - Image links without alt -->
<a href="/home">
  <img src="logo.png">
</a>

The Fix

<!-- ✓ Solution 1: Add aria-label -->
<a href="/cart" aria-label="Shopping cart">
  <i class="icon-cart" aria-hidden="true"></i>
</a>

<!-- ✓ Solution 2: Add screen reader text -->
<a href="/cart">
  <i class="icon-cart" aria-hidden="true"></i>
  <span class="sr-only">Shopping cart</span>
</a>

<!-- ✓ Solution 3: Use alt text on image -->
<a href="/home">
  <img src="logo.png" alt="AccessAudit home">
</a>

Time to Fix

⏱️ 2 minutes per link


5. Missing Skip Navigation (Found on 91% of Sites)

The Problem

Keyboard users must tab through the entire navigation on every page.

The Fix

<!-- Add this as first element in <body> -->
<a href="#main-content" class="skip-link">
  Skip to main content
</a>

<!-- ... navigation here ... -->

<main id="main-content">
  <!-- Your page content -->
</main>

CSS for Skip Link

/* Only show on keyboard focus */
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: #000;
  color: #fff;
  padding: 8px;
  text-decoration: none;
  z-index: 100;
}

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

Time to Fix

⏱️ 5 minutes once, benefits entire site


6. Missing Page Language (Found on 82% of Sites)

The Problem

Screen readers don't know which language to use for pronunciation.

How to Identify

<!-- ❌ Problem -->
<!DOCTYPE html>
<html>
  <head>

The Fix

<!-- ✓ Solution -->
<!DOCTYPE html>
<html lang="en">
  <head>

For multi-language sections:

<!-- Page in English, section in Spanish -->
<html lang="en">
  <body>
    <p>Welcome to our site.</p>
    <blockquote lang="es">
      Bienvenidos a nuestro sitio.
    </blockquote>
  </body>
</html>

Time to Fix

⏱️ 30 seconds


7. Poor Heading Structure (Found on 68% of Sites)

The Problem

Headings out of order confuse screen reader users navigating by headings.

How to Identify

<!-- ❌ Problem - Skipped levels -->
<h1>Page Title</h1>
<h3>Section Title</h3>  <!-- Skipped h2 -->
<h2>Subsection</h2>      <!-- Out of order -->

The Fix

<!-- ✓ Solution - Logical hierarchy -->
<h1>Page Title</h1>
  <h2>Main Section</h2>
    <h3>Subsection</h3>
    <h3>Another Subsection</h3>
  <h2>Another Main Section</h2>
    <h3>Subsection</h3>

Rules to Follow

  1. One H1 per page (page title)
  2. Don't skip levels (h1 → h2 → h3, not h1 → h3)
  3. Use headings for structure, not styling
  4. Order matters - keep hierarchy logical

If Design Conflicts

<!-- Use aria-level for visual vs. semantic hierarchy -->
<h2 class="looks-like-h4" aria-level="2">
  Semantically H2, Visually H4
</h2>

Time to Fix

⏱️ 10 minutes to audit and fix


8. No Focus Indicators (Found on 71% of Sites)

The Problem

Keyboard users can't see where they are on the page.

How to Identify

/* ❌ Problem - Focus removed */
*:focus {
  outline: none;
}

button:focus,
a:focus {
  outline: 0;
}

The Fix

/* ✓ Solution - Custom focus styles */
*:focus {
  outline: 2px solid #0066CC;
  outline-offset: 2px;
}

/* Enhanced for specific elements */
button:focus {
  outline: 2px solid #0066CC;
  outline-offset: 2px;
  box-shadow: 0 0 0 4px rgba(0, 102, 204, 0.2);
}

/* Visible focus, hidden when using mouse */
*:focus:not(:focus-visible) {
  outline: none;
}

*:focus-visible {
  outline: 2px solid #0066CC;
  outline-offset: 2px;
}

Time to Fix

⏱️ 5 minutes for global styles


9. Missing ARIA Labels on Buttons (Found on 56% of Sites)

The Problem

Icon-only buttons have no accessible name.

How to Identify

<!-- ❌ Problem -->
<button><i class="icon-close"></i></button>
<button>×</button>
<button><img src="menu.svg"></button>

The Fix

<!-- ✓ Solution 1: aria-label -->
<button aria-label="Close dialog">
  <i class="icon-close" aria-hidden="true"></i>
</button>

<!-- ✓ Solution 2: Screen reader text -->
<button>
  <i class="icon-close" aria-hidden="true"></i>
  <span class="sr-only">Close dialog</span>
</button>

<!-- ✓ Solution 3: title attribute (less preferred) -->
<button title="Close dialog">
  <i class="icon-close"></i>
</button>

Time to Fix

⏱️ 2 minutes per button


10. Inaccessible Modals (Found on 63% of Sites)

The Problem

Focus isn't trapped in modals, keyboard users can't close them, or screen readers don't announce them.

The Fix

<!-- Accessible modal structure -->
<div
  role="dialog"
  aria-labelledby="modal-title"
  aria-describedby="modal-desc"
  aria-modal="true"
>
  <h2 id="modal-title">Confirm Action</h2>
  <p id="modal-desc">Are you sure you want to delete this item?</p>

  <button onclick="confirmAction()">Confirm</button>
  <button onclick="closeModal()" aria-label="Cancel and close dialog">
    Cancel
  </button>
</div>

JavaScript for Focus Management

function openModal(modal) {
  // Store currently focused element
  const previousFocus = document.activeElement

  // Show modal
  modal.style.display = 'block'

  // Move focus to modal
  modal.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])').focus()

  // Trap focus
  modal.addEventListener('keydown', (e) => {
    if (e.key === 'Tab') {
      trapFocus(e, modal)
    }
    if (e.key === 'Escape') {
      closeModal(modal, previousFocus)
    }
  })
}

function closeModal(modal, previousFocus) {
  modal.style.display = 'none'
  // Return focus to trigger element
  previousFocus.focus()
}

Time to Fix

⏱️ 15 minutes with focus trap logic


Quick Wins Summary

If you're short on time, prioritize these fixes:

  1. 5 minutes: Add page language (<html lang="en">)
  2. 5 minutes: Add skip navigation link
  3. 10 minutes: Fix form labels
  4. 15 minutes: Add alt text to images
  5. 20 minutes: Fix color contrast in CSS

Total: 55 minutes to fix the most critical issues.


How to Prevent These Issues

1. Use Automated Scanning

Run AccessAudit on every deployment to catch issues before they go live.

2. Include Accessibility in Code Reviews

Add an accessibility checklist to your PR template:

  • [ ] All images have alt text
  • [ ] Forms have labels
  • [ ] Color contrast passes
  • [ ] Keyboard navigation works

3. Test with Real Users

Nothing beats testing with actual screen reader users and keyboard-only navigation.

4. Use Linting Tools

  • eslint-plugin-jsx-a11y (React)
  • axe-core (any framework)
  • pa11y (CI/CD integration)

Need Help?

AccessAudit automatically detects all these issues and provides fix recommendations with copy-paste code.

Scan your website for free →


Found this helpful? Share it with your team and help make the web more accessible for everyone.

Tags

#fixes#wcag#tutorial#development

Ready to Make Your Website Accessible?

Scan your entire site for WCAG compliance issues in minutes.

Start Free Trial