Skip to content
Blog

Web Accessibility: WCAG 2.2 for Developers

WCAG 2.2 is the accessibility standard your product will be measured against. Practical success criteria, testable checks, and fixes you can ship this sprint.

Published on August 10, 2026

AI Assistant

Accessibility gets treated as a nice-to-have until a legal letter arrives or a customer with a screen reader hits your checkout. The standard behind both — and behind the European Accessibility Act (EAA) — is WCAG 2.2: 13 guidelines organized under four principles and scored at three levels (A, AA, AAA). If you ship to the EU, “WCAG 2.2 AA” is increasingly the legal floor, not a stretch goal.

In this post, you will learn the four WCAG principles, the highest-impact success criteria with concrete fixes, what changed in 2.2, and how to fold checks into your pipeline instead of auditing after the fact.

The four principles: POUR

Every WCAG criterion hangs under one principle. If you remember nothing else, remember these four:

  • Perceivable — content must be presentable to all senses. Text alternatives, captions, contrast, no information-by-color-only.
  • Operable — interface must be usable by any input. Keyboard navigation, no seizure-triggering flashing, enough time, no traps.
  • Understandable — content and UI must be readable. Predictable navigation, input assistance, plain language.
  • Robust — content must work across assistive tech. Valid markup, proper roles, name/role/value exposed.

What’s new in WCAG 2.2

WCAG 2.2 keeps all of 2.1’s criteria (they never change across versions) and adds 9 new ones. The ones that bite developers hardest:

  • 2.5.7 Dragging Movements (AA) — any drag interaction must have a single-pointer alternative (click, tap, or keyboard).
  • 2.5.8 Target Size (Minimum) (AA) — interactive targets must be at least 24×24 CSS pixels. Small tap targets fail.
  • 3.2.6 Consistent Help (A) — help mechanisms (contact, help page) must be in the same relative order across pages.
  • 3.3.7 Redundant Entry (A) — don’t ask users to re-enter the same information (e.g. email twice) without offering autofill.
  • 3.3.8 Accessible Authentication (Minimum) (AA) — don’t require the user to solve cognitive tests (CAPTCHAs) to log in. If you must, provide an alternative or let a password manager or copy-paste do the work.

Notably, 2.2 removed the obsolete 4.1.1 Parsing criterion (valid markup is no longer a conformance criterion — modern browser/AT handling made it redundant).

The criteria that matter most for developers

If you have a limited budget, start with the criteria that cover the most users and are objectively testable:

1. Non-text Content (1.1.1, A). Every image needs alt. Decorative images get alt="", informative images get a real description, and text-in-images is an instant fail:

<!-- Informative: describe what's depicted -->
<img src="chart.png" alt="Revenue grew from $1M to $2.4M between Q1 and Q4" />

<!-- Decorative: empty alt hides it from the screen reader -->
<img src="divider.png" alt="" />

<!-- Functional: the link text, not a description -->
<a href="/downloads/guide.pdf"><img src="icon-pdf.png" alt="Download the guide (PDF)" /></a>

2. Contrast (Minimum) 1.4.3, AA. Text needs a 4.5:1 contrast ratio against its background (3:1 for large text and UI components). Run your palette through a contrast checker before shipping the design system, not after:

/* ❌ text-ink on white measures ~2.9:1 — fails AA */
.text-muted { color: #8a8a8a; }

/* ✅ bump to #6b6b6b or darker — passes 4.5:1 on white */
.text-muted { color: #5a5a5a; }

3. Keyboard (2.1.1, A) and No Keyboard Trap (2.1.2, A). Everything must be reachable and operable by keyboard. Tab order follows DOM order, focus styles must be visible, and you must never trap focus in a modal without an exit:

:focus-visible {
  outline: 2px solid var(--color-brand-500);
  outline-offset: 2px;
}
<!-- A dialog that traps focus must offer an escape -->
<dialog role="dialog" aria-modal="true" aria-labelledby="dialog-title">
  <h2 id="dialog-title">Confirm delete</h2>
  <button>Cancel</button>
  <button>Delete</button>  <!-- Esc and the Cancel button both exit -->
</dialog>

4. Name, Role, Value (4.1.2, A) / Parsing robustness. Every interactive element must expose a name, role, and current value to assistive tech. The fix is usually honest semantics + an accessible label:

<!-- ❌ A div pretending to be a button has no name/role/keyboard support -->
<div class="like" onClick={like}><span>♥</span></div>

<!-- ✅ A real button with an accessible name -->
<button aria-pressed={liked} onClick={like} aria-label={liked ? "Unlike" : "Like"}>♥</button>

5. Form labels and error identification (3.3.1, 3.3.2, A). Every input needs a programmatic label, and errors must be identified by text — not color or a placeholder:

<label for="email">Email address</label>
<input id="email" name="email" type="email" aria-describedby="email-hint" />
<p id="email-hint" class="error">Please enter a valid email address.</p>

The new 2.2 criteria you’ll hit in real products

Target size is the one your QA will trip on: buttons smaller than 24×24px fail. Fix the most common offender — icon-only controls:

.icon-button {
  width: 24px;
  height: 24px;
  /* or add invisible padding if the visible icon is smaller */
}
.icon-button::before { content: ""; position: absolute; inset: -4px; }

And accessible authentication (3.3.8) is the one your sign-in flow will trip on: if you ask “what’s your grandmother’s maiden name” or a hard CAPTCHA, you fail AA. Prefer one-time codes, passkeys, or a password manager — and never require solving a puzzle as the only path in.

Folding checks into your pipeline

Don’t audit accessibility at the end. Wire it in:

  1. Automated checks in CI — axe-core (or Lighthouse’s accessibility run) catches 25-40% of issues instantly. Fail the build on critical violations.
  2. A11y linting in the editorjsx-a11y for React, eslint-plugin-vuejs-accessibility, etc., surface alt/aria mistakes at authoring time.
  3. Contrast gates in the design system — token linting rejects colors that fail 4.5:1.
  4. Manual screen-reader pass — once a month, walk your flows in NVDA/VoiceOver. Automation can’t catch unlabeled landmarks, reading order, or focus order.

Remember the honest caveat: automated tools pass many things that still fail. A heading styled as a link, an empty <button> with only CSS content, or a focus order that jumps — automation misses these. Combine tooling with a human pass.

Putting It All Together

A ready-to-run a11y checkbook — axe-core wired into a CI step, an eslint-plugin-jsx-a11y config, a contrast-safe token set, and a manual screen-reader checklist. Drop it in, run the audits against your staging, and fix by criterion rather than by “guess and hope.”

Conclusion & Next Steps

You now know the POUR principles, the highest-impact WCAG 2.2 criteria, what changed in 2.2 (target size, dragging, accessible auth), and how to fold checks into CI. Next steps: run axe against your top five pages, fix the color-contrast failures at the token level, and start a manual screen-reader pass on your core flow — the automated + human combination is what actually ships an accessible product.

References / Sources