Accessibility audit checklist with pass/fail marks next to WCAG criteria on a clipboard with a magnifying glass

Accessibility Audit 2026: Why 94% of Sites Fail WCAG (and How to Fix It)

The WebAIM Million study continues to report that over 94% of the top million websites have detectable WCAG failures. That number has barely budged since 2019, despite increased awareness, better tooling, and growing legal pressure. The failures are not exotic edge cases — they are the same basic issues year after year: low contrast text, missing alt text, empty links, missing form labels, and broken keyboard navigation.

This guide is for developers and site owners who want to fix the issues that actually cause the most failures. Not aspirational accessibility theory — the specific, fixable problems that make up the bulk of real-world WCAG failures in 2026, with code-level solutions you can implement today.

The Six Failures That Account for 96% of Errors

WebAIM's 2026 data shows the same pattern as every previous year. These six issues account for nearly all detectable errors:

1. Low Contrast Text (83% of sites)

Text that does not meet the 4.5:1 contrast ratio for normal text or 3:1 for large text. The most common offenders: light grey placeholder text, muted body text on light backgrounds, and white text on coloured buttons.

Fix:

/* FAIL: contrast ratio 2.8:1 */
.text-muted { color: #999; background: #fff; }

/* PASS: contrast ratio 4.6:1 */
.text-muted { color: #696969; background: #fff; }

The human-centric design trends guide discusses warm colour palettes. When shifting to warmer tones, check every text/background combination. A warm palette does not inherently fail contrast, but designers often use lighter secondary text that drops below the threshold.

Use browser DevTools contrast checker (inspect the element, check the colour property) or an automated tool during development.

2. Missing Alternative Text (58% of sites)

Images without alt attributes, or with empty alt="" on images that convey meaningful content. The distinction matters: decorative images should have alt="" to hide them from screen readers. Content images need descriptive alt text.

Fix:

<!-- Decorative: correct empty alt -->
<img src="divider.svg" alt="" role="presentation">

<!-- Content image: descriptive alt -->
<img src="/img/hero/guide-typography-1600x900.jpg"
     alt="Close-up of well-set body text showing optimal line length and spacing on cream paper"
     width="1600" height="900">

The alt text should describe what the image shows, not what the image is for. "Hero image for the typography guide" is metadata, not a description. "Close-up of well-set body text showing optimal line length and spacing" describes the visual content.

3. Empty Links (50% of sites)

Links that have no accessible text. Typically: icon-only links without aria-labels, or links wrapped around images without alt text.

Fix:

<!-- FAIL: no accessible text -->
<a href="/search/">
  <svg viewBox="0 0 16 16">...</svg>
</a>

<!-- PASS: aria-label provides accessible text -->
<a href="/search/" aria-label="Search the site">
  <svg viewBox="0 0 16 16" aria-hidden="true">...</svg>
</a>

The SVG gets aria-hidden="true" because its visual content is decorative — the link's purpose is communicated by the aria-label.

4. Missing Form Labels (46% of sites)

Form inputs without associated <label> elements. Screen readers cannot announce what an input is for without a label.

Fix:

<!-- FAIL: no label -->
<input type="email" placeholder="Your email">

<!-- PASS: visible label -->
<label for="email">Email address</label>
<input type="email" id="email" placeholder="[email protected]">

<!-- PASS: hidden label for design constraints -->
<label for="search" class="sr-only">Search query</label>
<input type="search" id="search" placeholder="Search pages, guides, demos…">

Placeholder text is not a label. It disappears when the user starts typing, leaving them with no indication of what the field expects.

5. Missing Document Language (19% of sites)

No lang attribute on the <html> element. Screen readers need this to select the correct pronunciation rules.

Fix:

<html lang="en">

One attribute. The simplest fix on this list and still missing on nearly one in five sites.

6. Empty Buttons (27% of sites)

Buttons with no accessible text — usually icon-only buttons without labels.

Fix identical to empty links: Add aria-label to the button, and aria-hidden="true" to the decorative icon.

Keyboard Navigation

Beyond the six most common failures, broken keyboard navigation is the most impactful accessibility problem because it completely blocks users who cannot use a mouse.

Focus Visibility

Every interactive element must have a visible focus indicator. The default browser focus ring is acceptable if you do not override it. If you do override it, your custom focus styles must be clearly visible:

:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

/* Remove outline on click for mouse users */
:focus:not(:focus-visible) {
  outline: none;
}

The :focus-visible pseudo-class shows the focus ring only for keyboard navigation, not mouse clicks. This is the correct modern pattern.

Tab Order

Tab order should follow the visual layout. If CSS rearranges elements (grid order, flexbox order, absolute positioning), the tab order may not match. The semantic HTML layouts guide covers this: DOM order should match visual order.

Focus Trapping in Modals

When a modal is open, Tab and Shift+Tab must cycle within the modal, not escape to the page behind it. When the modal closes, focus must return to the element that opened it.

// Simplified focus trap
const modal = document.querySelector('.modal');
const focusableElements = modal.querySelectorAll(
  'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])'
);
const firstElement = focusableElements[0];
const lastElement = focusableElements[focusableElements.length - 1];

modal.addEventListener('keydown', (e) => {
  if (e.key === 'Tab') {
    if (e.shiftKey && document.activeElement === firstElement) {
      e.preventDefault();
      lastElement.focus();
    } else if (!e.shiftKey && document.activeElement === lastElement) {
      e.preventDefault();
      firstElement.focus();
    }
  }
});

ARIA: The Most Misused Accessibility Tool

ARIA (Accessible Rich Internet Applications) attributes are meant to fill gaps where HTML semantics fall short. In practice, ARIA is more often misused than correctly applied. The first rule of ARIA: do not use ARIA if a native HTML element can do the job.

Common ARIA mistakes:

<!-- WRONG: div with ARIA role when button element works -->
<div role="button" tabindex="0" onclick="submit()">Submit</div>

<!-- RIGHT: native button element -->
<button type="submit">Submit</button>

<!-- WRONG: aria-label duplicating visible text -->
<button aria-label="Close dialog">Close dialog</button>

<!-- RIGHT: aria-label when icon-only -->
<button aria-label="Close dialog">
  <svg aria-hidden="true">...</svg>
</button>

The native <button> element provides keyboard activation (Enter and Space), focus management, and form submission for free. A <div> with role="button" requires you to manually implement all of that.

Automated Testing Strategy

Automated tools catch approximately 30% of accessibility issues. The other 70% require manual testing. But that 30% includes the most common failures.

Build-Time Testing

Integrate axe-core or pa11y into your build pipeline:

# Test with pa11y during CI
pa11y https://locallylost.com/guides/ --standard WCAG2AA

This catches contrast failures, missing alt text, missing labels, and structural issues on every build.

Browser Extension Testing

The axe DevTools extension provides real-time accessibility auditing in Chrome and Firefox. Run it on every page during development. The SVG and UI icons guide covers accessible icon implementation — test those patterns with axe to verify.

Manual Testing Checklist

  1. Navigate the entire page using only the keyboard (Tab, Shift+Tab, Enter, Escape)
  2. Test with a screen reader (VoiceOver on Mac, NVDA on Windows)
  3. Zoom to 200% and verify no content is cut off or overlapping
  4. Disable CSS and verify content is still logically ordered
  5. Check all images with a tool that identifies missing or empty alt text

Checklist

  • [ ] All text meets 4.5:1 contrast ratio (3:1 for large text)
  • [ ] Every meaningful image has descriptive alt text
  • [ ] Every link has accessible text (visible or aria-label)
  • [ ] Every form input has an associated label
  • [ ] <html lang="en"> (or appropriate language) is set
  • [ ] Every button has accessible text
  • [ ] :focus-visible styles are visible and distinctive
  • [ ] Tab order matches visual layout
  • [ ] Modals trap focus and return focus on close
  • [ ] ARIA roles only used where native HTML elements cannot serve
  • [ ] Automated testing (axe-core or pa11y) integrated into build
  • [ ] Manual keyboard navigation tested on all pages

FAQ

Is WCAG 2.2 the current standard? Yes. WCAG 2.2 added criteria around focus appearance, dragging alternatives, and consistent help placement. WCAG 3.0 is still in development and not yet a conformance target.

How do I prioritise accessibility fixes? Start with the six most common failures listed above. They cover the vast majority of automated findings. Then address keyboard navigation. Then tackle ARIA and screen reader-specific issues.

Does accessibility slow down development? Initial implementation adds modest time. Retrofitting an inaccessible site adds significant time. The cheapest accessibility is accessibility built in from the start.

Next Steps

AccessibilityWCAGUX