Back to Blog
·14 min read·AccessGuard Team

The Complete WCAG Compliance Checklist for 2026: Audit Your Website Step by Step

# The Complete WCAG Compliance Checklist for 2026: Audit Your Website Step by Step

If you have ever tried to make a website accessible and felt overwhelmed by the sheer volume of guidelines, you are not alone. A structured WCAG compliance checklist is the single most effective tool for cutting through the complexity, organizing your audit, and making real progress toward an inclusive website. This guide gives you exactly that: a practical, developer-friendly walkthrough of every major WCAG 2.1 AA requirement, complete with code examples you can apply today.

The Web Content Accessibility Guidelines (WCAG) 2.1, published by the W3C, are the global benchmark for web accessibility. Level AA conformance is the standard referenced by most laws and regulations, including the ADA, the European Accessibility Act, and Section 508. Whether you are a front-end developer, a product owner, or a site administrator, this checklist will help you identify gaps and fix them systematically.

How to Use This WCAG Compliance Checklist

Before diving into individual criteria, establish a workflow:

  • Pick a scope. Audit your most-visited pages first: the homepage, key landing pages, forms, and checkout flows.
  • Combine automated and manual testing. Automated scanners catch roughly 30-40% of accessibility issues. The rest require manual review, keyboard testing, and screen reader verification.
  • Document everything. Track each issue, its WCAG success criterion, severity, and remediation status in a spreadsheet or issue tracker.
  • Retest after fixes. Accessibility is not a one-time task. Integrate checks into your CI/CD pipeline and design review process.
  • The checklist below is organized around the four foundational principles of WCAG: Perceivable, Operable, Understandable, and Robust (often abbreviated as POUR).

    ---

    Principle 1: Perceivable

    Users must be able to perceive all information and interface components. Content cannot be invisible to every sense available to a user.

    1.1 Text Alternatives (Success Criterion 1.1.1)

    Every non-text element needs a text alternative that serves the same purpose.

    What to check:

    • All elements have an alt attribute.
    • Decorative images use an empty alt="" so screen readers skip them.
    • Complex images (charts, infographics) have extended descriptions.
    • Icon fonts and SVGs used as controls have accessible labels.

    Common fix -- adding alt text:

    
    

    Bar chart showing monthly revenue increasing from $12k in January to $38k in June

    Common fix -- labeling an SVG icon button:

    1.2 Time-Based Media (Success Criteria 1.2.1 -- 1.2.5)

    Audio and video content must have alternatives.

    What to check:

    • Pre-recorded video has synchronized captions.
    • Pre-recorded audio has a transcript.
    • Pre-recorded video has an audio description track (or a descriptive transcript) for visual-only information.
    • Live video has real-time captions.

    1.3 Info and Relationships (Success Criterion 1.3.1)

    Structure conveyed visually must also be conveyed programmatically.

    What to check:

    • Headings use proper

      through
      tags in a logical hierarchy (no skipping levels).

    • Data tables use elements with scope attributes.
    • Form inputs are associated with elements.
    • Lists use
        ,
          , or
          markup rather than styled
          elements.
        1. Landmark regions (
          ,

      Common fix -- properly structured data table:

      Q1 Sales by Region
      Region January February March
      North America $142,000 $158,000 $173,000

      1.3 Meaningful Sequence and Sensory Characteristics (1.3.2 -- 1.3.3)

      • The DOM reading order matches the visual order.
      • Instructions do not rely solely on shape, color, size, or location (e.g., "click the green button on the right").

      1.4 Distinguishable Content (Success Criteria 1.4.1 -- 1.4.13)

      This group of criteria ensures users can see and hear content clearly.

      What to check:

      • Color is not the only indicator (1.4.1). Error states, links within text, and status changes use more than color alone -- add icons, underlines, or text labels.
      • Text contrast ratio is at least 4.5:1 for normal text and 3:1 for large text (1.4.3).
      • Non-text contrast for UI components and graphical objects is at least 3:1 (1.4.11).
      • Text can be resized up to 200% without loss of content or functionality (1.4.4).
      • Content reflows at 320 CSS pixels wide without horizontal scrolling (1.4.10).
      • Text spacing can be overridden without breaking layout (1.4.12).

      Common fix -- ensuring sufficient link contrast within text:

      /* Links within body text need to be distinguishable
      

      without relying on color alone */

      p a {

      color: #0055b3; / 4.9:1 ratio against white /

      text-decoration: underline; / non-color indicator /

      }

      p a:hover,

      p a:focus {

      color: #003d80;

      text-decoration-thickness: 2px;

      }

      Common fix -- supporting user text spacing overrides:

      /* Avoid fixed heights on text containers.
      

      Use min-height or let the container grow. */

      .card-body {

      min-height: 4rem; / not height: 4rem /

      padding: 1em;

      overflow: visible; / not overflow: hidden /

      }

      ---

      Principle 2: Operable

      All interface components and navigation must be operable by all users, including those who rely on keyboards, switches, or voice control.

      2.1 Keyboard Accessible (Success Criteria 2.1.1 -- 2.1.4)

      What to check:

      • Every interactive element is reachable and operable with the keyboard alone.
      • There are no keyboard traps -- users can always Tab away from a component.
      • Custom widgets (dropdowns, modals, sliders) follow WAI-ARIA authoring practices for keyboard interaction.

      Common fix -- making a custom button keyboard accessible:

      
      

      Submit

      onclick="submitForm()"

      onkeydown="if(event.key==='Enter'||event.key===' ')submitForm()">

      Submit

      2.2 Enough Time (Success Criteria 2.2.1 -- 2.2.2)

      • Users can turn off, adjust, or extend time limits (session timeouts, auto-advancing carousels).
      • Moving, blinking, or auto-updating content can be paused, stopped, or hidden.

      2.3 Seizures and Physical Reactions (Success Criterion 2.3.1)

      • No content flashes more than three times per second.

      2.4 Navigable (Success Criteria 2.4.1 -- 2.4.10)

      This is one of the largest groups in your WCAG compliance checklist and one of the most impactful for usability.

      What to check:

      • A skip navigation link is the first focusable element on the page.
      • Every page has a descriptive </code>.</li> <li class="ml-4"><strong>Focus order</strong> is logical and follows the visual layout.</li> <li class="ml-4"><strong>Link purpose</strong> is clear from the link text alone (avoid "click here" or "read more" without context).</li> <li class="ml-4">Multiple ways to find pages exist (navigation menu, sitemap, search).</li> <li class="ml-4">Headings and labels accurately describe content.</li> <li class="ml-4"><strong>Focus is visible</strong> on all interactive elements.</li> </ul> <p class="text-gray-700 leading-relaxed my-4"><strong>Common fix -- skip navigation link:</strong></p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code><body> <p class="text-gray-700 leading-relaxed my-4"> <a href="#main-content" class="skip-link">Skip to main content</a></p> <p class="text-gray-700 leading-relaxed my-4"> <header><!-- site header and nav --></header></p> <p class="text-gray-700 leading-relaxed my-4"> <main id="main-content"></p> <p class="text-gray-700 leading-relaxed my-4"> <!-- page content --></p> <p class="text-gray-700 leading-relaxed my-4"> </main></p> <p class="text-gray-700 leading-relaxed my-4"></body></p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code>.skip-link { <p class="text-gray-700 leading-relaxed my-4"> position: absolute;</p> <p class="text-gray-700 leading-relaxed my-4"> left: -9999px;</p> <p class="text-gray-700 leading-relaxed my-4"> top: auto;</p> <p class="text-gray-700 leading-relaxed my-4"> width: 1px;</p> <p class="text-gray-700 leading-relaxed my-4"> height: 1px;</p> <p class="text-gray-700 leading-relaxed my-4"> overflow: hidden;</p> <p class="text-gray-700 leading-relaxed my-4">}</p> <p class="text-gray-700 leading-relaxed my-4">.skip-link:focus {</p> <p class="text-gray-700 leading-relaxed my-4"> position: fixed;</p> <p class="text-gray-700 leading-relaxed my-4"> top: 0;</p> <p class="text-gray-700 leading-relaxed my-4"> left: 0;</p> <p class="text-gray-700 leading-relaxed my-4"> width: auto;</p> <p class="text-gray-700 leading-relaxed my-4"> height: auto;</p> <p class="text-gray-700 leading-relaxed my-4"> padding: 0.75em 1.5em;</p> <p class="text-gray-700 leading-relaxed my-4"> background: #000;</p> <p class="text-gray-700 leading-relaxed my-4"> color: #fff;</p> <p class="text-gray-700 leading-relaxed my-4"> z-index: 10000;</p> <p class="text-gray-700 leading-relaxed my-4"> font-size: 1rem;</p> <p class="text-gray-700 leading-relaxed my-4">}</p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <h3 class="text-xl font-bold mt-8 mb-3">2.5 Input Modalities (Success Criteria 2.5.1 -- 2.5.4)</h3> <ul class="list-disc space-y-2 my-4 pl-4"><li class="ml-4">Pointer gestures that require multipoint or path-based input (pinch, swipe) have single-pointer alternatives.</li> <li class="ml-4">Pointer actions can be cancelled (use <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm">mouseup</code> / <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm">keyup</code> rather than <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm">mousedown</code> / <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm">keydown</code> for activation).</li> <li class="ml-4">Visible labels match accessible names so voice control users can activate controls.</li> <li class="ml-4">Motion-based input (shake to undo) has a conventional UI alternative.</li> </ul> <p class="text-gray-700 leading-relaxed my-4">---</p> <h2 class="text-2xl font-bold mt-10 mb-4">Principle 3: Understandable</h2> <p class="text-gray-700 leading-relaxed my-4">Content and controls must be understandable to users.</p> <h3 class="text-xl font-bold mt-8 mb-3">3.1 Readable (Success Criteria 3.1.1 -- 3.1.2)</h3> <p class="text-gray-700 leading-relaxed my-4"><strong>What to check:</strong></p> <ul class="list-disc space-y-2 my-4 pl-4"><li class="ml-4">The page declares its language with a <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm">lang</code> attribute on <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm"><html></code>.</li> <li class="ml-4">Passages in a different language are marked up with their own <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm">lang</code> attribute.</li> </ul> <p class="text-gray-700 leading-relaxed my-4"><strong>Common fix:</strong></p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code><html lang="en"> <p class="text-gray-700 leading-relaxed my-4"> <body></p> <p class="text-gray-700 leading-relaxed my-4"> <p>Welcome to our site.</p></p> <p class="text-gray-700 leading-relaxed my-4"> <p lang="fr">Bienvenue sur notre site.</p></p> <p class="text-gray-700 leading-relaxed my-4"> </body></p> <p class="text-gray-700 leading-relaxed my-4"></html></p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <h3 class="text-xl font-bold mt-8 mb-3">3.2 Predictable (Success Criteria 3.2.1 -- 3.2.5)</h3> <ul class="list-disc space-y-2 my-4 pl-4"><li class="ml-4">Focusing on an element does not automatically trigger a change of context (like navigating to a new page).</li> <li class="ml-4">Changing a form input value does not automatically submit the form or navigate away without warning.</li> <li class="ml-4">Navigation patterns are consistent across pages.</li> </ul> <h3 class="text-xl font-bold mt-8 mb-3">3.3 Input Assistance (Success Criteria 3.3.1 -- 3.3.4)</h3> <p class="text-gray-700 leading-relaxed my-4">Forms are where most real-world accessibility failures happen. This section of the checklist deserves extra attention.</p> <p class="text-gray-700 leading-relaxed my-4"><strong>What to check:</strong></p> <ul class="list-disc space-y-2 my-4 pl-4"><li class="ml-4"><strong>Error identification</strong>: Errors are described in text and linked to the relevant field.</li> <li class="ml-4"><strong>Labels and instructions</strong>: Every input has a visible label and, where needed, format hints.</li> <li class="ml-4"><strong>Error suggestion</strong>: When an error is detected and a correction is known, it is suggested to the user.</li> <li class="ml-4"><strong>Error prevention</strong>: For legal, financial, or data-deletion actions, submissions are reversible, verified, or confirmed.</li> </ul> <p class="text-gray-700 leading-relaxed my-4"><strong>Common fix -- accessible inline error messages:</strong></p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code><div class="form-group"> <p class="text-gray-700 leading-relaxed my-4"> <label for="email">Email address</label></p> <p class="text-gray-700 leading-relaxed my-4"> <input</p> <p class="text-gray-700 leading-relaxed my-4"> type="email"</p> <p class="text-gray-700 leading-relaxed my-4"> id="email"</p> <p class="text-gray-700 leading-relaxed my-4"> name="email"</p> <p class="text-gray-700 leading-relaxed my-4"> aria-describedby="email-error"</p> <p class="text-gray-700 leading-relaxed my-4"> aria-invalid="true"</p> <p class="text-gray-700 leading-relaxed my-4"> ></p> <p class="text-gray-700 leading-relaxed my-4"> <p id="email-error" class="error-message" role="alert"></p> <p class="text-gray-700 leading-relaxed my-4"> Please enter a valid email address, for example name@domain.com</p> <p class="text-gray-700 leading-relaxed my-4"> </p></p> <p class="text-gray-700 leading-relaxed my-4"></div></p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code>.error-message { <p class="text-gray-700 leading-relaxed my-4"> color: #b30000; /<em> sufficient contrast </em>/</p> <p class="text-gray-700 leading-relaxed my-4"> font-size: 0.875rem;</p> <p class="text-gray-700 leading-relaxed my-4"> margin-top: 0.25rem;</p> <p class="text-gray-700 leading-relaxed my-4">}</p> <p class="text-gray-700 leading-relaxed my-4">input[aria-invalid="true"] {</p> <p class="text-gray-700 leading-relaxed my-4"> border: 2px solid #b30000;</p> <p class="text-gray-700 leading-relaxed my-4"> /<em> Also add an icon -- do not rely on border color alone </em>/</p> <p class="text-gray-700 leading-relaxed my-4"> background: url('error-icon.svg') no-repeat right 0.5rem center;</p> <p class="text-gray-700 leading-relaxed my-4"> background-size: 1rem;</p> <p class="text-gray-700 leading-relaxed my-4"> padding-right: 2rem;</p> <p class="text-gray-700 leading-relaxed my-4">}</p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <p class="text-gray-700 leading-relaxed my-4">---</p> <h2 class="text-2xl font-bold mt-10 mb-4">Principle 4: Robust</h2> <p class="text-gray-700 leading-relaxed my-4">Content must be robust enough to work reliably with current and future technologies, including assistive technologies.</p> <h3 class="text-xl font-bold mt-8 mb-3">4.1 Compatible (Success Criteria 4.1.1 -- 4.1.3)</h3> <p class="text-gray-700 leading-relaxed my-4"><strong>What to check:</strong></p> <ul class="list-disc space-y-2 my-4 pl-4"><li class="ml-4">HTML is well-formed and <strong>validates</strong> without critical parsing errors.</li> <li class="ml-4">All interactive elements have a <strong>name, role, and value</strong> that assistive technology can read.</li> <li class="ml-4"><strong>Status messages</strong> (success alerts, progress updates, cart item counts) are communicated to screen readers without stealing focus.</li> </ul> <p class="text-gray-700 leading-relaxed my-4"><strong>Common fix -- live region for status messages:</strong></p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code><!-- Cart count update announced to screen readers --> <p class="text-gray-700 leading-relaxed my-4"><div aria-live="polite" aria-atomic="true" class="cart-status"></p> <p class="text-gray-700 leading-relaxed my-4"> 3 items in your cart</p> <p class="text-gray-700 leading-relaxed my-4"></div></p> <p class="text-gray-700 leading-relaxed my-4"><!-- Form submission success message --></p> <p class="text-gray-700 leading-relaxed my-4"><div role="status" aria-live="polite"></p> <p class="text-gray-700 leading-relaxed my-4"> Your message has been sent successfully.</p> <p class="text-gray-700 leading-relaxed my-4"></div></p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <p class="text-gray-700 leading-relaxed my-4"><strong>Common fix -- custom select with proper ARIA roles:</strong></p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code><div role="combobox" aria-expanded="false" aria-haspopup="listbox" <p class="text-gray-700 leading-relaxed my-4"> aria-labelledby="color-label"></p> <p class="text-gray-700 leading-relaxed my-4"> <span id="color-label">Choose a color</span></p> <p class="text-gray-700 leading-relaxed my-4"> <input type="text" aria-autocomplete="list"</p> <p class="text-gray-700 leading-relaxed my-4"> aria-controls="color-listbox"></p> <p class="text-gray-700 leading-relaxed my-4"> <ul id="color-listbox" role="listbox" hidden></p> <p class="text-gray-700 leading-relaxed my-4"> <li role="option" id="opt-red">Red</li></p> <p class="text-gray-700 leading-relaxed my-4"> <li role="option" id="opt-blue">Blue</li></p> <p class="text-gray-700 leading-relaxed my-4"> <li role="option" id="opt-green">Green</li></p> <p class="text-gray-700 leading-relaxed my-4"> </ul></p> <p class="text-gray-700 leading-relaxed my-4"></div></p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <p class="text-gray-700 leading-relaxed my-4">---</p> <h2 class="text-2xl font-bold mt-10 mb-4">Quick-Reference WCAG Compliance Checklist</h2> <p class="text-gray-700 leading-relaxed my-4">Use this condensed list during development reviews and pull requests:</p> <p class="text-gray-700 leading-relaxed my-4">| Category | Check | WCAG SC |</p> <p class="text-gray-700 leading-relaxed my-4">|---|---|---|</p> <p class="text-gray-700 leading-relaxed my-4">| Images | All images have meaningful or empty <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm">alt</code> | 1.1.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| Video | Captions present and synchronized | 1.2.2 |</p> <p class="text-gray-700 leading-relaxed my-4">| Structure | Heading hierarchy is logical, no skipped levels | 1.3.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| Forms | Every input has a <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm"><label></code> | 1.3.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| Landmarks | Page uses <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm"><header></code>, <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm"><nav></code>, <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm"><main></code>, <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm"><footer></code> | 1.3.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| Color | Text contrast meets 4.5:1 (normal) or 3:1 (large) | 1.4.3 |</p> <p class="text-gray-700 leading-relaxed my-4">| Color | Info is not conveyed by color alone | 1.4.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| Reflow | Content works at 320px width, no horizontal scroll | 1.4.10 |</p> <p class="text-gray-700 leading-relaxed my-4">| Keyboard | All controls reachable and operable via keyboard | 2.1.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| Keyboard | No keyboard traps | 2.1.2 |</p> <p class="text-gray-700 leading-relaxed my-4">| Navigation | Skip link present | 2.4.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| Navigation | Page <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm"><title></code> is descriptive | 2.4.2 |</p> <p class="text-gray-700 leading-relaxed my-4">| Focus | Focus indicator visible on all interactive elements | 2.4.7 |</p> <p class="text-gray-700 leading-relaxed my-4">| Links | Link text describes destination | 2.4.4 |</p> <p class="text-gray-700 leading-relaxed my-4">| Language | <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm"><html></code> has <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm">lang</code> attribute | 3.1.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| Forms | Errors identified in text and linked to fields | 3.3.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| Forms | Labels and instructions provided | 3.3.2 |</p> <p class="text-gray-700 leading-relaxed my-4">| Parsing | HTML validates without critical errors | 4.1.1 |</p> <p class="text-gray-700 leading-relaxed my-4">| ARIA | Interactive widgets have name, role, value | 4.1.2 |</p> <p class="text-gray-700 leading-relaxed my-4">| Status | Status messages use <code class="bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm">aria-live</code> regions | 4.1.3 |</p> <p class="text-gray-700 leading-relaxed my-4">---</p> <h2 class="text-2xl font-bold mt-10 mb-4">Common Mistakes That Fail WCAG Audits</h2> <p class="text-gray-700 leading-relaxed my-4">Even experienced teams make these errors repeatedly. Watch for them in your code reviews:</p> <h3 class="text-xl font-bold mt-8 mb-3">Missing Focus Styles</h3> <p class="text-gray-700 leading-relaxed my-4">Removing the browser default outline without replacing it is one of the fastest ways to fail an audit.</p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code>/<em> Do NOT do this without a replacement </em>/ <p class="text-gray-700 leading-relaxed my-4">*:focus {</p> <p class="text-gray-700 leading-relaxed my-4"> outline: none;</p> <p class="text-gray-700 leading-relaxed my-4">}</p> <p class="text-gray-700 leading-relaxed my-4">/<em> Instead, create a custom focus indicator </em>/</p> <p class="text-gray-700 leading-relaxed my-4">:focus-visible {</p> <p class="text-gray-700 leading-relaxed my-4"> outline: 3px solid #1a73e8;</p> <p class="text-gray-700 leading-relaxed my-4"> outline-offset: 2px;</p> <p class="text-gray-700 leading-relaxed my-4"> border-radius: 2px;</p> <p class="text-gray-700 leading-relaxed my-4">}</p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <h3 class="text-xl font-bold mt-8 mb-3">Placeholder Text as Labels</h3> <p class="text-gray-700 leading-relaxed my-4">Placeholder text disappears when the user starts typing, leaving them without context. It also typically fails contrast requirements.</p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code><!-- Incorrect: placeholder instead of label --> <p class="text-gray-700 leading-relaxed my-4"><input type="text" placeholder="Enter your name"></p> <p class="text-gray-700 leading-relaxed my-4"><!-- Correct: visible label plus optional placeholder --></p> <label for="full-name">Full name</label> <p class="text-gray-700 leading-relaxed my-4"><input type="text" id="full-name" placeholder="e.g., Jane Doe"></p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <h3 class="text-xl font-bold mt-8 mb-3">Auto-Playing Media</h3> <p class="text-gray-700 leading-relaxed my-4">Video or audio that plays automatically can be disorienting and make a page unusable for screen reader users.</p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code><!-- Incorrect --> <p class="text-gray-700 leading-relaxed my-4"><video autoplay src="promo.mp4"></video></p> <p class="text-gray-700 leading-relaxed my-4"><!-- Correct: no autoplay, with controls --></p> <p class="text-gray-700 leading-relaxed my-4"><video controls src="promo.mp4"></p> <p class="text-gray-700 leading-relaxed my-4"> <track kind="captions" src="promo-captions.vtt" srclang="en" label="English"></p> <p class="text-gray-700 leading-relaxed my-4"></video></p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <h3 class="text-xl font-bold mt-8 mb-3">Inaccessible Modal Dialogs</h3> <p class="text-gray-700 leading-relaxed my-4">Modals that do not trap focus or that lack a close mechanism are a frequent source of keyboard traps.</p> <pre class="bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6"><code><div role="dialog" aria-modal="true" aria-labelledby="dialog-title"> <p class="text-gray-700 leading-relaxed my-4"> <h2 id="dialog-title">Confirm your selection</h2></p> <p class="text-gray-700 leading-relaxed my-4"> <p>Are you sure you want to proceed?</p></p> <p class="text-gray-700 leading-relaxed my-4"> <button type="button">Cancel</button></p> <p class="text-gray-700 leading-relaxed my-4"> <button type="button">Confirm</button></p> <p class="text-gray-700 leading-relaxed my-4"></div></p> <p class="text-gray-700 leading-relaxed my-4"></code></pre></p> <p class="text-gray-700 leading-relaxed my-4">When the modal opens, move focus to the first interactive element inside it. When it closes, return focus to the element that triggered it. Ensure the Escape key closes the dialog.</p> <p class="text-gray-700 leading-relaxed my-4">---</p> <h2 class="text-2xl font-bold mt-10 mb-4">Testing Your WCAG Compliance Checklist</h2> <p class="text-gray-700 leading-relaxed my-4">A thorough audit combines multiple approaches:</p> <h3 class="text-xl font-bold mt-8 mb-3">Automated Testing</h3> <p class="text-gray-700 leading-relaxed my-4">Run a scanner to catch low-hanging fruit: missing alt text, contrast failures, missing labels, and invalid ARIA. Automated tools are excellent for catching structural issues at scale, but they cannot evaluate whether alt text is meaningful or whether focus order makes logical sense.</p> <h3 class="text-xl font-bold mt-8 mb-3">Manual Keyboard Testing</h3> <p class="text-gray-700 leading-relaxed my-4">Unplug your mouse and navigate through every page. Verify that:</p> <ul class="list-disc space-y-2 my-4 pl-4"><li class="ml-4">You can reach all interactive elements with Tab.</li> <li class="ml-4">You can activate buttons with Enter and Space.</li> <li class="ml-4">Dropdowns and menus respond to arrow keys.</li> <li class="ml-4">Modals trap focus correctly and release it on close.</li> </ul> <h3 class="text-xl font-bold mt-8 mb-3">Screen Reader Testing</h3> <p class="text-gray-700 leading-relaxed my-4">Test with at least one screen reader. NVDA (free, Windows) or VoiceOver (built into macOS and iOS) are the most common choices. Listen for:</p> <ul class="list-disc space-y-2 my-4 pl-4"><li class="ml-4">Meaningful announcements on every interactive element.</li> <li class="ml-4">Correct reading order.</li> <li class="ml-4">Live region announcements for dynamic content.</li> </ul> <h3 class="text-xl font-bold mt-8 mb-3">Responsive and Zoom Testing</h3> <ul class="list-disc space-y-2 my-4 pl-4"><li class="ml-4">Zoom the browser to 200% and verify no content is lost.</li> <li class="ml-4">Set the viewport to 320px wide and check for horizontal scrolling.</li> <li class="ml-4">Override text spacing (line-height, letter-spacing, word-spacing) and confirm nothing breaks.</li> </ul> <p class="text-gray-700 leading-relaxed my-4">---</p> <h2 class="text-2xl font-bold mt-10 mb-4">Building Accessibility Into Your Workflow</h2> <p class="text-gray-700 leading-relaxed my-4">The most successful accessibility programs are not audit-driven. They are process-driven. Here is how to shift left:</p> <li class="ml-4 list-decimal"><strong>Design phase</strong>: Use contrast-checked color palettes. Annotate designs with heading levels, focus order, and alternative text.</li> <li class="ml-4 list-decimal"><strong>Development phase</strong>: Use semantic HTML by default. Lint for accessibility issues with tools like axe-linter or eslint-plugin-jsx-a11y.</li> <li class="ml-4 list-decimal"><strong>Code review phase</strong>: Add accessibility to your review checklist. Reviewers should tab through new components in the browser before approving a pull request.</li> <li class="ml-4 list-decimal"><strong>CI/CD phase</strong>: Integrate automated accessibility testing into your pipeline so regressions are caught before deployment.</li> <li class="ml-4 list-decimal"><strong>Monitoring phase</strong>: Run scheduled scans across your site to catch issues introduced by content editors, third-party scripts, or CMS updates.</li> <p class="text-gray-700 leading-relaxed my-4">---</p> <h2 class="text-2xl font-bold mt-10 mb-4">Start Your Audit Today with AccessGuard</h2> <p class="text-gray-700 leading-relaxed my-4">Working through a WCAG compliance checklist manually is essential, but it does not scale across hundreds or thousands of pages. That is where automation fills the gap.</p> <p class="text-gray-700 leading-relaxed my-4"><strong>AccessGuard's free website accessibility scanner</strong> crawls your site, tests against WCAG 2.1 AA criteria, and delivers a prioritized report of issues with specific code-level remediation guidance. You get a clear picture of where you stand in minutes, not weeks.</p> <p class="text-gray-700 leading-relaxed my-4">Whether you are starting your first audit or maintaining an already-accessible site, AccessGuard helps you catch regressions, track progress over time, and demonstrate compliance with confidence.</p> <p class="text-gray-700 leading-relaxed my-4"><a href="/" class="text-primary hover:text-primary-dark underline" target="_blank" rel="noopener noreferrer">Run your free accessibility scan now</a> and see how your site measures up against this WCAG compliance checklist.</p></div><div class="mt-16 bg-blue-50 rounded-2xl p-8 text-center space-y-4"><h3 class="text-xl font-bold text-foreground">Check your website's accessibility now</h3><p class="text-muted">Free instant scan. No sign-up required.</p><a class="inline-block bg-primary text-white font-bold px-8 py-3 rounded-xl hover:bg-primary-dark transition-colors" href="/">Scan Your Website Free</a></div></article></div><!--$--><!--/$--><script src="/_next/static/chunks/33c6e7ef9aa43899.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[39756,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"default\"]\n3:I[37457,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"default\"]\n5:I[97367,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"OutletBoundary\"]\n6:\"$Sreact.suspense\"\n8:I[97367,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"ViewportBoundary\"]\na:I[97367,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"MetadataBoundary\"]\nc:I[68027,[],\"default\"]\n:HL[\"/_next/static/chunks/702d3fef7db5bec3.css\",\"style\"]\n:HL[\"/_next/static/media/83afe278b6a6bb3c-s.p.3a6ba036.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"wCg7x4m_fCb2yIQRhnHRa\",\"c\":[\"\",\"blog\",\"wcag-compliance-checklist-2026\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"blog\",{\"children\":[[\"slug\",\"wcag-compliance-checklist-2026\",\"d\"],{\"children\":[\"__PAGE__\",{}]}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/702d3fef7db5bec3.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"inter_5901b7c6-module__ec5Qua__variable antialiased\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[\"$L4\",[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/7c92e96509cd355e.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L5\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@7\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$6\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",[]],\"S\":true}\n"])</script><script>self.__next_f.push([1,"d:I[22016,[\"/_next/static/chunks/7c92e96509cd355e.js\"],\"\"]\ne:T994c,"])</script><script>self.__next_f.push([1,"\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e# The Complete WCAG Compliance Checklist for 2026: Audit Your Website Step by Step\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eIf you have ever tried to make a website accessible and felt overwhelmed by the sheer volume of guidelines, you are not alone. A structured \u003cstrong\u003eWCAG compliance checklist\u003c/strong\u003e is the single most effective tool for cutting through the complexity, organizing your audit, and making real progress toward an inclusive website. This guide gives you exactly that: a practical, developer-friendly walkthrough of every major WCAG 2.1 AA requirement, complete with code examples you can apply today.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eThe Web Content Accessibility Guidelines (WCAG) 2.1, published by the W3C, are the global benchmark for web accessibility. Level AA conformance is the standard referenced by most laws and regulations, including the ADA, the European Accessibility Act, and Section 508. Whether you are a front-end developer, a product owner, or a site administrator, this checklist will help you identify gaps and fix them systematically.\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003eHow to Use This WCAG Compliance Checklist\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eBefore diving into individual criteria, establish a workflow:\u003c/p\u003e\n\n\u003cli class=\"ml-4 list-decimal\"\u003e\u003cstrong\u003ePick a scope.\u003c/strong\u003e Audit your most-visited pages first: the homepage, key landing pages, forms, and checkout flows.\u003c/li\u003e\n\u003cli class=\"ml-4 list-decimal\"\u003e\u003cstrong\u003eCombine automated and manual testing.\u003c/strong\u003e Automated scanners catch roughly 30-40% of accessibility issues. The rest require manual review, keyboard testing, and screen reader verification.\u003c/li\u003e\n\u003cli class=\"ml-4 list-decimal\"\u003e\u003cstrong\u003eDocument everything.\u003c/strong\u003e Track each issue, its WCAG success criterion, severity, and remediation status in a spreadsheet or issue tracker.\u003c/li\u003e\n\u003cli class=\"ml-4 list-decimal\"\u003e\u003cstrong\u003eRetest after fixes.\u003c/strong\u003e Accessibility is not a one-time task. Integrate checks into your CI/CD pipeline and design review process.\u003c/li\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eThe checklist below is organized around the four foundational principles of WCAG: Perceivable, Operable, Understandable, and Robust (often abbreviated as POUR).\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e---\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003ePrinciple 1: Perceivable\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eUsers must be able to perceive all information and interface components. Content cannot be invisible to every sense available to a user.\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e1.1 Text Alternatives (Success Criterion 1.1.1)\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eEvery non-text element needs a text alternative that serves the same purpose.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eWhat to check:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eAll \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cimg\u003e\u003c/code\u003e elements have an \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003ealt\u003c/code\u003e attribute.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eDecorative images use an empty \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003ealt=\"\"\u003c/code\u003e so screen readers skip them.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eComplex images (charts, infographics) have extended descriptions.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eIcon fonts and SVGs used as controls have accessible labels.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- adding alt text:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003c!-- Incorrect: missing alt --\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cimg src=\"dashboard-chart.png\"\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c!-- Correct: descriptive alt --\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cimg src=\"dashboard-chart.png\" alt=\"Bar chart showing monthly revenue increasing from $12k in January to $38k in June\"\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c!-- Correct: decorative image --\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cimg src=\"decorative-swirl.svg\" alt=\"\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- labeling an SVG icon button:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003cbutton aria-label=\"Close dialog\"\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003csvg aria-hidden=\"true\" focusable=\"false\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cuse href=\"#icon-close\"\u003e\u003c/use\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c/svg\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/button\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e1.2 Time-Based Media (Success Criteria 1.2.1 -- 1.2.5)\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eAudio and video content must have alternatives.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eWhat to check:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003ePre-recorded video has synchronized captions.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003ePre-recorded audio has a transcript.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003ePre-recorded video has an audio description track (or a descriptive transcript) for visual-only information.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eLive video has real-time captions.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e1.3 Info and Relationships (Success Criterion 1.3.1)\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eStructure conveyed visually must also be conveyed programmatically.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eWhat to check:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eHeadings use proper \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003ch1\u003e\u003c/code\u003e through \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003ch6\u003e\u003c/code\u003e tags in a logical hierarchy (no skipping levels).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eData tables use \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cth\u003e\u003c/code\u003e elements with \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003escope\u003c/code\u003e attributes.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eForm inputs are associated with \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003clabel\u003e\u003c/code\u003e elements.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eLists use \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cul\u003e\u003c/code\u003e, \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003col\u003e\u003c/code\u003e, or \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cdl\u003e\u003c/code\u003e markup rather than styled \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cdiv\u003e\u003c/code\u003e elements.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eLandmark regions (\u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cheader\u003e\u003c/code\u003e, \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cnav\u003e\u003c/code\u003e, \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cmain\u003e\u003c/code\u003e, \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cfooter\u003e\u003c/code\u003e) are used correctly.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- properly structured data table:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003ctable\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ccaption\u003eQ1 Sales by Region\u003c/caption\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cthead\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ctr\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cth scope=\"col\"\u003eRegion\u003c/th\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cth scope=\"col\"\u003eJanuary\u003c/th\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cth scope=\"col\"\u003eFebruary\u003c/th\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cth scope=\"col\"\u003eMarch\u003c/th\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c/tr\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c/thead\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ctbody\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ctr\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cth scope=\"row\"\u003eNorth America\u003c/th\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ctd\u003e$142,000\u003c/td\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ctd\u003e$158,000\u003c/td\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ctd\u003e$173,000\u003c/td\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c/tr\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c/tbody\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/table\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e1.3 Meaningful Sequence and Sensory Characteristics (1.3.2 -- 1.3.3)\u003c/h3\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eThe DOM reading order matches the visual order.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eInstructions do not rely solely on shape, color, size, or location (e.g., \"click the green button on the right\").\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e1.4 Distinguishable Content (Success Criteria 1.4.1 -- 1.4.13)\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eThis group of criteria ensures users can see and hear content clearly.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eWhat to check:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eColor is not the only indicator\u003c/strong\u003e (1.4.1). Error states, links within text, and status changes use more than color alone -- add icons, underlines, or text labels.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eText contrast ratio\u003c/strong\u003e is at least 4.5:1 for normal text and 3:1 for large text (1.4.3).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eNon-text contrast\u003c/strong\u003e for UI components and graphical objects is at least 3:1 (1.4.11).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eText can be \u003cstrong\u003eresized up to 200%\u003c/strong\u003e without loss of content or functionality (1.4.4).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eContent reflows\u003c/strong\u003e at 320 CSS pixels wide without horizontal scrolling (1.4.10).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eText spacing\u003c/strong\u003e can be overridden without breaking layout (1.4.12).\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- ensuring sufficient link contrast within text:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e/* Links within body text need to be distinguishable\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e without relying on color alone */\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003ep a {\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e color: #0055b3; /\u003cem\u003e 4.9:1 ratio against white \u003c/em\u003e/\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e text-decoration: underline; /\u003cem\u003e non-color indicator \u003c/em\u003e/\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e}\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003ep a:hover,\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003ep a:focus {\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e color: #003d80;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e text-decoration-thickness: 2px;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e}\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- supporting user text spacing overrides:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e/* Avoid fixed heights on text containers.\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e Use min-height or let the container grow. */\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e.card-body {\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e min-height: 4rem; /\u003cem\u003e not height: 4rem \u003c/em\u003e/\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e padding: 1em;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e overflow: visible; /\u003cem\u003e not overflow: hidden \u003c/em\u003e/\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e}\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e---\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003ePrinciple 2: Operable\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eAll interface components and navigation must be operable by all users, including those who rely on keyboards, switches, or voice control.\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e2.1 Keyboard Accessible (Success Criteria 2.1.1 -- 2.1.4)\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eWhat to check:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eEvery interactive element is reachable and operable with the keyboard alone.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eThere are no keyboard traps -- users can always Tab away from a component.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eCustom widgets (dropdowns, modals, sliders) follow WAI-ARIA authoring practices for keyboard interaction.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- making a custom button keyboard accessible:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003c!-- Incorrect: div acting as button, not keyboard accessible --\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cdiv class=\"btn\" onclick=\"submitForm()\"\u003eSubmit\u003c/div\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c!-- Correct: use a real button element --\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cbutton type=\"submit\" class=\"btn\"\u003eSubmit\u003c/button\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c!-- If you must use a div (rare), add role and keyboard handling --\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cdiv class=\"btn\" role=\"button\" tabindex=\"0\"\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e onclick=\"submitForm()\"\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e onkeydown=\"if(event.key==='Enter'||event.key===' ')submitForm()\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e Submit\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/div\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e2.2 Enough Time (Success Criteria 2.2.1 -- 2.2.2)\u003c/h3\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eUsers can turn off, adjust, or extend time limits (session timeouts, auto-advancing carousels).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eMoving, blinking, or auto-updating content can be paused, stopped, or hidden.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e2.3 Seizures and Physical Reactions (Success Criterion 2.3.1)\u003c/h3\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eNo content flashes more than three times per second.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e2.4 Navigable (Success Criteria 2.4.1 -- 2.4.10)\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eThis is one of the largest groups in your WCAG compliance checklist and one of the most impactful for usability.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eWhat to check:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eA \u003cstrong\u003eskip navigation\u003c/strong\u003e link is the first focusable element on the page.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eEvery page has a descriptive \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003ctitle\u003e\u003c/code\u003e.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eFocus order\u003c/strong\u003e is logical and follows the visual layout.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eLink purpose\u003c/strong\u003e is clear from the link text alone (avoid \"click here\" or \"read more\" without context).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eMultiple ways to find pages exist (navigation menu, sitemap, search).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eHeadings and labels accurately describe content.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eFocus is visible\u003c/strong\u003e on all interactive elements.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- skip navigation link:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003cbody\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ca href=\"#main-content\" class=\"skip-link\"\u003eSkip to main content\u003c/a\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cheader\u003e\u003c!-- site header and nav --\u003e\u003c/header\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cmain id=\"main-content\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c!-- page content --\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c/main\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/body\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e.skip-link {\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e position: absolute;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e left: -9999px;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e top: auto;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e width: 1px;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e height: 1px;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e overflow: hidden;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e}\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e.skip-link:focus {\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e position: fixed;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e top: 0;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e left: 0;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e width: auto;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e height: auto;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e padding: 0.75em 1.5em;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e background: #000;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e color: #fff;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e z-index: 10000;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e font-size: 1rem;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e}\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e2.5 Input Modalities (Success Criteria 2.5.1 -- 2.5.4)\u003c/h3\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003ePointer gestures that require multipoint or path-based input (pinch, swipe) have single-pointer alternatives.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003ePointer actions can be cancelled (use \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003emouseup\u003c/code\u003e / \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003ekeyup\u003c/code\u003e rather than \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003emousedown\u003c/code\u003e / \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003ekeydown\u003c/code\u003e for activation).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eVisible labels match accessible names so voice control users can activate controls.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eMotion-based input (shake to undo) has a conventional UI alternative.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e---\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003ePrinciple 3: Understandable\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eContent and controls must be understandable to users.\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e3.1 Readable (Success Criteria 3.1.1 -- 3.1.2)\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eWhat to check:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eThe page declares its language with a \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003elang\u003c/code\u003e attribute on \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003chtml\u003e\u003c/code\u003e.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003ePassages in a different language are marked up with their own \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003elang\u003c/code\u003e attribute.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003chtml lang=\"en\"\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cbody\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cp\u003eWelcome to our site.\u003c/p\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cp lang=\"fr\"\u003eBienvenue sur notre site.\u003c/p\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c/body\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/html\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e3.2 Predictable (Success Criteria 3.2.1 -- 3.2.5)\u003c/h3\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eFocusing on an element does not automatically trigger a change of context (like navigating to a new page).\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eChanging a form input value does not automatically submit the form or navigate away without warning.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eNavigation patterns are consistent across pages.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e3.3 Input Assistance (Success Criteria 3.3.1 -- 3.3.4)\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eForms are where most real-world accessibility failures happen. This section of the checklist deserves extra attention.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eWhat to check:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eError identification\u003c/strong\u003e: Errors are described in text and linked to the relevant field.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eLabels and instructions\u003c/strong\u003e: Every input has a visible label and, where needed, format hints.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eError suggestion\u003c/strong\u003e: When an error is detected and a correction is known, it is suggested to the user.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eError prevention\u003c/strong\u003e: For legal, financial, or data-deletion actions, submissions are reversible, verified, or confirmed.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- accessible inline error messages:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003cdiv class=\"form-group\"\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003clabel for=\"email\"\u003eEmail address\u003c/label\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cinput\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e type=\"email\"\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e id=\"email\"\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e name=\"email\"\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e aria-describedby=\"email-error\"\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e aria-invalid=\"true\"\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cp id=\"email-error\" class=\"error-message\" role=\"alert\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e Please enter a valid email address, for example name@domain.com\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c/p\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/div\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e.error-message {\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e color: #b30000; /\u003cem\u003e sufficient contrast \u003c/em\u003e/\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e font-size: 0.875rem;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e margin-top: 0.25rem;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e}\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003einput[aria-invalid=\"true\"] {\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e border: 2px solid #b30000;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e /\u003cem\u003e Also add an icon -- do not rely on border color alone \u003c/em\u003e/\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e background: url('error-icon.svg') no-repeat right 0.5rem center;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e background-size: 1rem;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e padding-right: 2rem;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e}\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e---\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003ePrinciple 4: Robust\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eContent must be robust enough to work reliably with current and future technologies, including assistive technologies.\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003e4.1 Compatible (Success Criteria 4.1.1 -- 4.1.3)\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eWhat to check:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eHTML is well-formed and \u003cstrong\u003evalidates\u003c/strong\u003e without critical parsing errors.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eAll interactive elements have a \u003cstrong\u003ename, role, and value\u003c/strong\u003e that assistive technology can read.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003e\u003cstrong\u003eStatus messages\u003c/strong\u003e (success alerts, progress updates, cart item counts) are communicated to screen readers without stealing focus.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- live region for status messages:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003c!-- Cart count update announced to screen readers --\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cdiv aria-live=\"polite\" aria-atomic=\"true\" class=\"cart-status\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e 3 items in your cart\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/div\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c!-- Form submission success message --\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cdiv role=\"status\" aria-live=\"polite\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e Your message has been sent successfully.\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/div\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eCommon fix -- custom select with proper ARIA roles:\u003c/strong\u003e\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003cdiv role=\"combobox\" aria-expanded=\"false\" aria-haspopup=\"listbox\"\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e aria-labelledby=\"color-label\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cspan id=\"color-label\"\u003eChoose a color\u003c/span\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cinput type=\"text\" aria-autocomplete=\"list\"\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e aria-controls=\"color-listbox\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cul id=\"color-listbox\" role=\"listbox\" hidden\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cli role=\"option\" id=\"opt-red\"\u003eRed\u003c/li\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cli role=\"option\" id=\"opt-blue\"\u003eBlue\u003c/li\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cli role=\"option\" id=\"opt-green\"\u003eGreen\u003c/li\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003c/ul\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/div\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e---\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003eQuick-Reference WCAG Compliance Checklist\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eUse this condensed list during development reviews and pull requests:\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Category | Check | WCAG SC |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e|---|---|---|\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Images | All images have meaningful or empty \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003ealt\u003c/code\u003e | 1.1.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Video | Captions present and synchronized | 1.2.2 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Structure | Heading hierarchy is logical, no skipped levels | 1.3.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Forms | Every input has a \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003clabel\u003e\u003c/code\u003e | 1.3.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Landmarks | Page uses \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cheader\u003e\u003c/code\u003e, \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cnav\u003e\u003c/code\u003e, \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cmain\u003e\u003c/code\u003e, \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003cfooter\u003e\u003c/code\u003e | 1.3.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Color | Text contrast meets 4.5:1 (normal) or 3:1 (large) | 1.4.3 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Color | Info is not conveyed by color alone | 1.4.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Reflow | Content works at 320px width, no horizontal scroll | 1.4.10 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Keyboard | All controls reachable and operable via keyboard | 2.1.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Keyboard | No keyboard traps | 2.1.2 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Navigation | Skip link present | 2.4.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Navigation | Page \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003ctitle\u003e\u003c/code\u003e is descriptive | 2.4.2 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Focus | Focus indicator visible on all interactive elements | 2.4.7 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Links | Link text describes destination | 2.4.4 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Language | \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003e\u003chtml\u003e\u003c/code\u003e has \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003elang\u003c/code\u003e attribute | 3.1.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Forms | Errors identified in text and linked to fields | 3.3.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Forms | Labels and instructions provided | 3.3.2 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Parsing | HTML validates without critical errors | 4.1.1 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| ARIA | Interactive widgets have name, role, value | 4.1.2 |\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e| Status | Status messages use \u003ccode class=\"bg-gray-100 text-red-700 px-1.5 py-0.5 rounded text-sm\"\u003earia-live\u003c/code\u003e regions | 4.1.3 |\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e---\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003eCommon Mistakes That Fail WCAG Audits\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eEven experienced teams make these errors repeatedly. Watch for them in your code reviews:\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003eMissing Focus Styles\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eRemoving the browser default outline without replacing it is one of the fastest ways to fail an audit.\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e/\u003cem\u003e Do NOT do this without a replacement \u003c/em\u003e/\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e*:focus {\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e outline: none;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e}\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e/\u003cem\u003e Instead, create a custom focus indicator \u003c/em\u003e/\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e:focus-visible {\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e outline: 3px solid #1a73e8;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e outline-offset: 2px;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e border-radius: 2px;\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e}\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003ePlaceholder Text as Labels\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003ePlaceholder text disappears when the user starts typing, leaving them without context. It also typically fails contrast requirements.\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003c!-- Incorrect: placeholder instead of label --\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cinput type=\"text\" placeholder=\"Enter your name\"\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c!-- Correct: visible label plus optional placeholder --\u003e\u003c/p\u003e\n\u003clabel for=\"full-name\"\u003eFull name\u003c/label\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cinput type=\"text\" id=\"full-name\" placeholder=\"e.g., Jane Doe\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003eAuto-Playing Media\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eVideo or audio that plays automatically can be disorienting and make a page unusable for screen reader users.\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003c!-- Incorrect --\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cvideo autoplay src=\"promo.mp4\"\u003e\u003c/video\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c!-- Correct: no autoplay, with controls --\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cvideo controls src=\"promo.mp4\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ctrack kind=\"captions\" src=\"promo-captions.vtt\" srclang=\"en\" label=\"English\"\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/video\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003eInaccessible Modal Dialogs\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eModals that do not trap focus or that lack a close mechanism are a frequent source of keyboard traps.\u003c/p\u003e\n\n\u003cpre class=\"bg-gray-900 text-gray-100 rounded-xl p-4 overflow-x-auto my-6\"\u003e\u003ccode\u003e\u003cdiv role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"dialog-title\"\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003ch2 id=\"dialog-title\"\u003eConfirm your selection\u003c/h2\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cp\u003eAre you sure you want to proceed?\u003c/p\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cbutton type=\"button\"\u003eCancel\u003c/button\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e \u003cbutton type=\"button\"\u003eConfirm\u003c/button\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/div\u003e\u003c/p\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eWhen the modal opens, move focus to the first interactive element inside it. When it closes, return focus to the element that triggered it. Ensure the Escape key closes the dialog.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e---\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003eTesting Your WCAG Compliance Checklist\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eA thorough audit combines multiple approaches:\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003eAutomated Testing\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eRun a scanner to catch low-hanging fruit: missing alt text, contrast failures, missing labels, and invalid ARIA. Automated tools are excellent for catching structural issues at scale, but they cannot evaluate whether alt text is meaningful or whether focus order makes logical sense.\u003c/p\u003e\n\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003eManual Keyboard Testing\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eUnplug your mouse and navigate through every page. Verify that:\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eYou can reach all interactive elements with Tab.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eYou can activate buttons with Enter and Space.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eDropdowns and menus respond to arrow keys.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eModals trap focus correctly and release it on close.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003eScreen Reader Testing\u003c/h3\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eTest with at least one screen reader. NVDA (free, Windows) or VoiceOver (built into macOS and iOS) are the most common choices. Listen for:\u003c/p\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eMeaningful announcements on every interactive element.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eCorrect reading order.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eLive region announcements for dynamic content.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 class=\"text-xl font-bold mt-8 mb-3\"\u003eResponsive and Zoom Testing\u003c/h3\u003e\n\n\u003cul class=\"list-disc space-y-2 my-4 pl-4\"\u003e\u003cli class=\"ml-4\"\u003eZoom the browser to 200% and verify no content is lost.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eSet the viewport to 320px wide and check for horizontal scrolling.\u003c/li\u003e\n\u003cli class=\"ml-4\"\u003eOverride text spacing (line-height, letter-spacing, word-spacing) and confirm nothing breaks.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e---\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003eBuilding Accessibility Into Your Workflow\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eThe most successful accessibility programs are not audit-driven. They are process-driven. Here is how to shift left:\u003c/p\u003e\n\n\u003cli class=\"ml-4 list-decimal\"\u003e\u003cstrong\u003eDesign phase\u003c/strong\u003e: Use contrast-checked color palettes. Annotate designs with heading levels, focus order, and alternative text.\u003c/li\u003e\n\u003cli class=\"ml-4 list-decimal\"\u003e\u003cstrong\u003eDevelopment phase\u003c/strong\u003e: Use semantic HTML by default. Lint for accessibility issues with tools like axe-linter or eslint-plugin-jsx-a11y.\u003c/li\u003e\n\u003cli class=\"ml-4 list-decimal\"\u003e\u003cstrong\u003eCode review phase\u003c/strong\u003e: Add accessibility to your review checklist. Reviewers should tab through new components in the browser before approving a pull request.\u003c/li\u003e\n\u003cli class=\"ml-4 list-decimal\"\u003e\u003cstrong\u003eCI/CD phase\u003c/strong\u003e: Integrate automated accessibility testing into your pipeline so regressions are caught before deployment.\u003c/li\u003e\n\u003cli class=\"ml-4 list-decimal\"\u003e\u003cstrong\u003eMonitoring phase\u003c/strong\u003e: Run scheduled scans across your site to catch issues introduced by content editors, third-party scripts, or CMS updates.\u003c/li\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e---\u003c/p\u003e\n\n\u003ch2 class=\"text-2xl font-bold mt-10 mb-4\"\u003eStart Your Audit Today with AccessGuard\u003c/h2\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eWorking through a WCAG compliance checklist manually is essential, but it does not scale across hundreds or thousands of pages. That is where automation fills the gap.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003cstrong\u003eAccessGuard's free website accessibility scanner\u003c/strong\u003e crawls your site, tests against WCAG 2.1 AA criteria, and delivers a prioritized report of issues with specific code-level remediation guidance. You get a clear picture of where you stand in minutes, not weeks.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003eWhether you are starting your first audit or maintaining an already-accessible site, AccessGuard helps you catch regressions, track progress over time, and demonstrate compliance with confidence.\u003c/p\u003e\n\n\u003cp class=\"text-gray-700 leading-relaxed my-4\"\u003e\u003ca href=\"/\" class=\"text-primary hover:text-primary-dark underline\" target=\"_blank\" rel=\"noopener noreferrer\"\u003eRun your free accessibility scan now\u003c/a\u003e and see how your site measures up against this WCAG compliance checklist.\u003c/p\u003e"])</script><script>self.__next_f.push([1,"4:[\"$\",\"div\",null,{\"className\":\"min-h-screen bg-white\",\"children\":[[\"$\",\"nav\",null,{\"className\":\"max-w-6xl mx-auto px-6 py-4 flex items-center justify-between border-b border-gray-100\",\"children\":[[\"$\",\"$Ld\",null,{\"href\":\"/\",\"className\":\"flex items-center gap-2\",\"children\":[[\"$\",\"svg\",null,{\"className\":\"h-8 w-8 text-primary\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"strokeWidth\":2,\"stroke\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"d\":\"M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z\"}]}],[\"$\",\"span\",null,{\"className\":\"text-xl font-bold text-foreground\",\"children\":\"AccessGuard\"}]]}],[\"$\",\"$Ld\",null,{\"href\":\"/\",\"className\":\"bg-primary text-white text-sm font-semibold px-5 py-2.5 rounded-lg hover:bg-primary-dark transition-colors\",\"children\":\"Free Scan\"}]]}],[\"$\",\"article\",null,{\"className\":\"max-w-3xl mx-auto px-6 pt-12 pb-20\",\"children\":[[\"$\",\"$Ld\",null,{\"href\":\"/blog\",\"className\":\"text-sm text-muted hover:text-primary transition-colors inline-flex items-center gap-1 mb-8\",\"children\":[[\"$\",\"svg\",null,{\"className\":\"h-4 w-4\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"strokeWidth\":2,\"stroke\":\"currentColor\",\"children\":[\"$\",\"path\",null,{\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"d\":\"M15.75 19.5L8.25 12l7.5-7.5\"}]}],\"Back to Blog\"]}],[\"$\",\"header\",null,{\"className\":\"mb-8\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex items-center gap-3 text-sm text-muted mb-3\",\"children\":[[\"$\",\"time\",null,{\"dateTime\":\"2026-02-24\",\"children\":\"February 24, 2026\"}],[\"$\",\"span\",null,{\"children\":\"·\"}],[\"$\",\"span\",null,{\"children\":[14,\" min read\"]}],[\"$\",\"span\",null,{\"children\":\"·\"}],[\"$\",\"span\",null,{\"children\":\"AccessGuard Team\"}]]}],[\"$\",\"h1\",null,{\"className\":\"text-3xl sm:text-4xl font-extrabold text-foreground leading-tight\",\"children\":\"The Complete WCAG Compliance Checklist for 2026: Audit Your Website Step by Step\"}],[\"$\",\"div\",null,{\"className\":\"flex gap-2 mt-4\",\"children\":[]}]]}],[\"$\",\"div\",null,{\"className\":\"prose max-w-none\",\"dangerouslySetInnerHTML\":{\"__html\":\"$e\"}}],\"$Lf\"]}]]}]\n"])</script><script>self.__next_f.push([1,"f:[\"$\",\"div\",null,{\"className\":\"mt-16 bg-blue-50 rounded-2xl p-8 text-center space-y-4\",\"children\":[[\"$\",\"h3\",null,{\"className\":\"text-xl font-bold text-foreground\",\"children\":\"Check your website's accessibility now\"}],[\"$\",\"p\",null,{\"className\":\"text-muted\",\"children\":\"Free instant scan. No sign-up required.\"}],[\"$\",\"$Ld\",null,{\"href\":\"/\",\"className\":\"inline-block bg-primary text-white font-bold px-8 py-3 rounded-xl hover:bg-primary-dark transition-colors\",\"children\":\"Scan Your Website Free\"}]]}]\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[27201,[\"/_next/static/chunks/ff1a16fafef87110.js\",\"/_next/static/chunks/d2be314c3ece3fbe.js\"],\"IconMark\"]\n7:null\n"])</script><script>self.__next_f.push([1,"b:[[\"$\",\"title\",\"0\",{\"children\":\"The Complete WCAG Compliance Checklist for 2026: Audit Your Website Step by Step | AccessGuard Blog\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Use this WCAG compliance checklist to audit your website against WCAG 2.1 AA standards. Practical fixes, code examples, and actionable steps for developers.\"}],[\"$\",\"meta\",\"2\",{\"name\":\"keywords\",\"content\":\"accessibility checker,WCAG compliance,ADA compliance,website accessibility,accessibility scanner,WCAG 2.1,accessibility audit,a11y checker,web accessibility testing\"}],[\"$\",\"meta\",\"3\",{\"name\":\"robots\",\"content\":\"index, follow\"}],[\"$\",\"meta\",\"4\",{\"name\":\"google-site-verification\",\"content\":\"LoLB0JA05qcI6u3y54pKFl86H3uqMxurVdxEwEPdYUs\"}],[\"$\",\"meta\",\"5\",{\"property\":\"og:title\",\"content\":\"The Complete WCAG Compliance Checklist for 2026: Audit Your Website Step by Step\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:description\",\"content\":\"Use this WCAG compliance checklist to audit your website against WCAG 2.1 AA standards. Practical fixes, code examples, and actionable steps for developers.\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:type\",\"content\":\"article\"}],[\"$\",\"meta\",\"8\",{\"property\":\"article:published_time\",\"content\":\"2026-02-24\"}],[\"$\",\"meta\",\"9\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"10\",{\"name\":\"twitter:title\",\"content\":\"AccessGuard - Free Website Accessibility Checker\"}],[\"$\",\"meta\",\"11\",{\"name\":\"twitter:description\",\"content\":\"Scan your website for accessibility issues in seconds. Get actionable fixes for WCAG 2.1 compliance.\"}],[\"$\",\"link\",\"12\",{\"rel\":\"icon\",\"href\":\"/favicon.ico?favicon.0b3bf435.ico\",\"sizes\":\"256x256\",\"type\":\"image/x-icon\"}],[\"$\",\"$L10\",\"13\",{}]]\n"])</script></body></html>