Files
gh-jamesrochabrun-skills-fr…/skills/frontend-designer/references/accessibility_checklist.md
2025-11-29 18:49:21 +08:00

15 KiB
Raw Blame History

WCAG 2.1 AA Accessibility Checklist

Comprehensive checklist for ensuring your frontend meets WCAG 2.1 Level AA compliance.

Perceivable

Information and user interface components must be presentable to users in ways they can perceive.

1.1 Text Alternatives

1.1.1 Non-text Content (Level A)

  • All images have appropriate alt text
  • Decorative images use empty alt (alt="")
  • Complex images have detailed descriptions
  • Icons have text alternatives or aria-label
  • Charts/graphs have text descriptions
  • CAPTCHAs have alternative forms
<!-- Good examples -->
<img src="logo.png" alt="Company Name">
<img src="decorative.png" alt="" role="presentation">
<button aria-label="Close dialog"><span aria-hidden="true">×</span></button>

1.2 Time-based Media

1.2.1 Audio-only and Video-only (Level A)

  • Audio-only content has transcripts
  • Video-only content has transcripts or audio description

1.2.2 Captions (Level A)

  • All pre-recorded videos have captions
  • Captions are synchronized and accurate

1.2.3 Audio Description or Media Alternative (Level A)

  • Videos have audio descriptions or text alternative

1.2.4 Captions (Live) (Level AA)

  • Live videos have captions

1.2.5 Audio Description (Level AA)

  • All pre-recorded videos have audio descriptions
<video controls>
  <source src="video.mp4" type="video/mp4">
  <track kind="captions" src="captions.vtt" srclang="en" label="English">
  <track kind="descriptions" src="descriptions.vtt" srclang="en" label="English descriptions">
</video>

1.3 Adaptable

1.3.1 Info and Relationships (Level A)

  • Semantic HTML used correctly (headings, lists, tables)
  • Form labels properly associated with inputs
  • Related form controls are grouped
  • Visual presentation matches code structure
  • ARIA roles used when needed
<!-- Semantic structure -->
<main>
  <h1>Main Heading</h1>
  <section>
    <h2>Section Heading</h2>
    <p>Content</p>
  </section>
</main>

<!-- Proper form labels -->
<label for="email">Email address</label>
<input type="email" id="email" name="email">

<!-- Grouped controls -->
<fieldset>
  <legend>Contact preferences</legend>
  <label><input type="checkbox" name="email"> Email</label>
  <label><input type="checkbox" name="phone"> Phone</label>
</fieldset>

1.3.2 Meaningful Sequence (Level A)

  • Reading order is logical
  • Tab order follows visual flow
  • CSS positioning doesn't disrupt reading order

1.3.3 Sensory Characteristics (Level A)

  • Instructions don't rely solely on shape
  • Instructions don't rely solely on size
  • Instructions don't rely solely on location
  • Instructions don't rely solely on sound
<!-- ❌ Bad -->
<p>Click the blue button on the right</p>

<!-- ✅ Good -->
<p>Click the "Submit" button to continue</p>

1.3.4 Orientation (Level AA)

  • Content works in portrait and landscape
  • No orientation restrictions unless essential

1.3.5 Identify Input Purpose (Level AA)

  • Input fields use autocomplete attribute when appropriate
<input type="email" name="email" autocomplete="email">
<input type="tel" name="phone" autocomplete="tel">
<input type="text" name="address" autocomplete="street-address">

1.4 Distinguishable

1.4.1 Use of Color (Level A)

  • Color not used as only visual means of conveying information
  • Color not used as only way to distinguish interactive elements
  • Links are distinguishable without color alone
/* ✅ Good - underline + color */
a {
  color: blue;
  text-decoration: underline;
}

/* Or use icons, borders, etc. */
.error {
  color: red;
  border-left: 4px solid red;
  padding-left: 12px;
}
.error::before {
  content: "⚠ ";
}

1.4.2 Audio Control (Level A)

  • Auto-playing audio can be paused
  • Auto-playing audio stops after 3 seconds
  • Volume controls available

1.4.3 Contrast (Minimum) (Level AA)

  • Normal text: 4.5:1 contrast ratio
  • Large text (18pt+): 3:1 contrast ratio
  • UI components: 3:1 contrast ratio
  • Graphical objects: 3:1 contrast ratio
/* Check with contrast checkers */
.text {
  color: #595959; /* 7:1 on white ✅ */
  background: #FFFFFF;
}

.button {
  color: #FFFFFF;
  background: #0066FF; /* 4.6:1 ✅ */
  border: 2px solid #0052CC; /* 3:1 ✅ */
}

1.4.4 Resize Text (Level AA)

  • Text can be resized to 200% without loss of content
  • No horizontal scrolling at 200% zoom
  • Use relative units (rem, em)
/* ✅ Good */
body {
  font-size: 1rem; /* Respects user preferences */
}

h1 {
  font-size: 2.5rem; /* Scales with body */
}

/* ❌ Avoid */
.text {
  font-size: 14px; /* Fixed size */
}

1.4.5 Images of Text (Level AA)

  • Text is text, not images
  • Exception: logos, essential presentations

1.4.10 Reflow (Level AA)

  • Content reflows at 320px viewport width
  • No horizontal scrolling (except tables, diagrams)
  • Responsive design implemented
/* Mobile-first responsive */
.container {
  width: 100%;
  max-width: 1200px;
  padding: 1rem;
}

@media (min-width: 768px) {
  .container {
    padding: 2rem;
  }
}

1.4.11 Non-text Contrast (Level AA)

  • UI components: 3:1 contrast against background
  • Graphical objects: 3:1 contrast
  • Focus indicators: 3:1 contrast

1.4.12 Text Spacing (Level AA)

  • Content adapts to increased text spacing
  • Line height: at least 1.5x font size
  • Paragraph spacing: at least 2x font size
  • Letter spacing: at least 0.12x font size
  • Word spacing: at least 0.16x font size
/* Ensure content doesn't break */
body {
  line-height: 1.5;
}

p {
  margin-bottom: 2em;
}

1.4.13 Content on Hover or Focus (Level AA)

  • Additional content (tooltips, dropdowns) is dismissible
  • Hoverable content stays visible when hovering over it
  • Content remains visible until dismissed or no longer relevant
/* Tooltip stays visible when hovering over it */
.tooltip:hover .tooltip-content,
.tooltip .tooltip-content:hover {
  display: block;
}

Operable

User interface components and navigation must be operable.

2.1 Keyboard Accessible

2.1.1 Keyboard (Level A)

  • All functionality available via keyboard
  • No keyboard traps
  • Logical tab order
  • Custom controls are keyboard accessible
<!-- Custom button needs tabindex and keyboard handlers -->
<div role="button" tabindex="0"
     onclick="handleClick()"
     onkeydown="if(event.key==='Enter'||event.key===' ') handleClick()">
  Click me
</div>

2.1.2 No Keyboard Trap (Level A)

  • Focus can move away from all components
  • Instructions provided if non-standard exit method

2.1.4 Character Key Shortcuts (Level A)

  • Single-key shortcuts can be turned off
  • Or remapped by user
  • Or only active when component has focus

2.2 Enough Time

2.2.1 Timing Adjustable (Level A)

  • Time limits can be turned off, adjusted, or extended
  • User warned before time expires
  • At least 20 seconds to extend

2.2.2 Pause, Stop, Hide (Level A)

  • Moving content can be paused
  • Auto-updating content can be paused/stopped
  • Blinking content can be stopped
<!-- Provide controls -->
<div class="carousel">
  <button aria-label="Pause carousel"></button>
  <button aria-label="Play carousel"></button>
</div>

2.3 Seizures and Physical Reactions

2.3.1 Three Flashes or Below Threshold (Level A)

  • No content flashes more than 3 times per second
  • Or flashes are below general flash/red flash thresholds

2.4 Navigable

2.4.1 Bypass Blocks (Level A)

  • Skip navigation link provided
  • Landmark regions defined
  • Headings structure content
<!-- Skip link (visually hidden until focused) -->
<a href="#main" class="skip-link">Skip to main content</a>

<header>
  <nav aria-label="Main navigation">...</nav>
</header>

<main id="main">
  <h1>Page Title</h1>
</main>
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: #000;
  color: #fff;
  padding: 8px;
  z-index: 100;
}

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

2.4.2 Page Titled (Level A)

  • Page has descriptive title
  • Title identifies page content
<title>Contact Us - Company Name</title>

2.4.3 Focus Order (Level A)

  • Focus order is logical and intuitive
  • Matches visual order
  • No positive tabindex values
/* ❌ Avoid */
.element { tabindex: 5; }

/* ✅ Use */
.element { tabindex: 0; }  /* In natural order */
.element { tabindex: -1; } /* Programmatic focus only */

2.4.4 Link Purpose (Level A)

  • Link text describes destination
  • Context is clear
  • Avoid "click here" or "read more"
<!-- ❌ Bad -->
<a href="/report.pdf">Click here</a>

<!-- ✅ Good -->
<a href="/report.pdf">Download 2024 Annual Report (PDF, 2MB)</a>

2.4.5 Multiple Ways (Level AA)

  • Multiple ways to find pages (menu, search, sitemap)
  • Exception: pages that are steps in a process

2.4.6 Headings and Labels (Level AA)

  • Headings describe content
  • Labels describe purpose
  • Headings and labels are clear

2.4.7 Focus Visible (Level AA)

  • Keyboard focus indicator is visible
  • Sufficient contrast (3:1)
  • Clearly indicates focused element
/* ✅ Strong focus indicator */
*:focus-visible {
  outline: 2px solid #0066FF;
  outline-offset: 2px;
}

/* Or custom focus styles */
button:focus-visible {
  box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.5);
}

2.5 Input Modalities

2.5.1 Pointer Gestures (Level A)

  • Complex gestures have single-pointer alternative
  • Path-based gestures have simple alternative

2.5.2 Pointer Cancellation (Level A)

  • Actions triggered on up-event (not down)
  • Or can be aborted/undone

2.5.3 Label in Name (Level A)

  • Visible label matches accessible name
  • Accessible name starts with visible text
<!-- ✅ Good - matches -->
<button aria-label="Submit form">Submit</button>

<!-- ❌ Bad - doesn't match -->
<button aria-label="Send">Submit</button>

2.5.4 Motion Actuation (Level A)

  • Device motion triggers have UI alternative
  • Can disable motion actuation

Understandable

Information and user interface operation must be understandable.

3.1 Readable

3.1.1 Language of Page (Level A)

  • Page language is identified
<html lang="en">

3.1.2 Language of Parts (Level AA)

  • Language changes are marked
<p>The French phrase <span lang="fr">c'est la vie</span> means "that's life".</p>

3.2 Predictable

3.2.1 On Focus (Level A)

  • Focusing an element doesn't trigger context change
  • No automatic form submission on focus

3.2.2 On Input (Level A)

  • Changing settings doesn't automatically cause context change
  • User is warned of automatic changes

3.2.3 Consistent Navigation (Level AA)

  • Navigation order is consistent across pages
  • Repeated navigation in same order

3.2.4 Consistent Identification (Level AA)

  • Components with same functionality are identified consistently
  • Icons mean the same thing throughout

3.3 Input Assistance

3.3.1 Error Identification (Level A)

  • Errors are identified in text
  • Error is described to user
<input type="email" aria-invalid="true" aria-describedby="email-error">
<span id="email-error" role="alert">Please enter a valid email address</span>

3.3.2 Labels or Instructions (Level A)

  • Labels provided for input
  • Instructions provided when needed
<label for="password">
  Password (must be at least 8 characters)
</label>
<input type="password" id="password" required minlength="8">

3.3.3 Error Suggestion (Level AA)

  • Errors suggest how to fix
  • Specific, actionable feedback
<span role="alert">
  Password must contain at least one uppercase letter,
  one number, and be at least 8 characters long.
</span>

3.3.4 Error Prevention (Level AA)

  • Legal/financial transactions are reversible
  • Data is checked and confirmed before submission
  • User can review and correct before submitting
<!-- Confirmation step -->
<div role="region" aria-labelledby="review-heading">
  <h2 id="review-heading">Review Your Order</h2>
  <!-- Show all details -->
  <button>Edit Order</button>
  <button>Confirm Purchase</button>
</div>

Robust

Content must be robust enough to be interpreted by a wide variety of user agents, including assistive technologies.

4.1 Compatible

4.1.1 Parsing (Level A) [Obsolete in WCAG 2.2]

  • Valid HTML (no duplicate IDs, proper nesting)

4.1.2 Name, Role, Value (Level A)

  • All UI components have accessible name
  • Roles are appropriate
  • States communicated to assistive tech
<!-- Custom checkbox -->
<div role="checkbox"
     aria-checked="false"
     aria-labelledby="label-id"
     tabindex="0">
</div>
<span id="label-id">Accept terms</span>

<!-- Button states -->
<button aria-pressed="false" aria-label="Mute">🔊</button>
<button aria-pressed="true" aria-label="Mute">🔇</button>

4.1.3 Status Messages (Level AA)

  • Status messages can be perceived by assistive tech
  • Use aria-live, role="status", role="alert"
<!-- Success message -->
<div role="status" aria-live="polite">
  Form submitted successfully!
</div>

<!-- Error message -->
<div role="alert" aria-live="assertive">
  Error: Connection lost. Please try again.
</div>

<!-- Loading state -->
<div aria-live="polite" aria-busy="true">
  Loading content...
</div>

Testing Checklist

Automated Testing

  • Run axe DevTools
  • Run Lighthouse accessibility audit
  • Run WAVE browser extension
  • HTML validator (W3C)
  • Color contrast checker

Manual Testing

  • Keyboard-only navigation
  • Screen reader testing (NVDA, JAWS, VoiceOver)
  • Zoom to 200% (text resize)
  • Test with browser zoom (page zoom)
  • Test in high contrast mode
  • Test with dark mode
  • Test responsive breakpoints

Screen Reader Testing

  • NVDA (Windows, free)
  • JAWS (Windows, paid)
  • VoiceOver (Mac/iOS, built-in)
  • TalkBack (Android, built-in)
  • ORCA (Linux, free)

Browser Testing

  • Chrome + screen reader
  • Firefox + screen reader
  • Safari + VoiceOver
  • Edge + screen reader

Quick Reference

Critical Items (Must Fix)

  1. Images have alt text
  2. Form inputs have labels
  3. Sufficient color contrast (4.5:1 text, 3:1 UI)
  4. Keyboard accessible (all functionality)
  5. Focus indicators visible
  6. No keyboard traps
  7. Semantic HTML (headings, landmarks)
  8. ARIA used correctly
  9. Page has title
  10. Language identified

Tools

Resources


"Accessibility is not a feature, it's a fundamental right."