Skip to main content

wcag-contrast-color-screen-reader

Implements WCAG 2.2 AA color contrast (4.5:1 text, 3:1 UI), semantic HTML landmarks, heading hierarchy, table markup, ARIA naming, live regions, and screen reader optimization for accessible web applications.

Zur Installation springen

Quellinformationen

Repository
paulpas/agent-skill-router
Letzte Quellaktivität
23. September 2026 um 21:59
Erkannte Sprache von SKILL.md
Englisch
Sterne
6
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
wcag-contrast-color-screen-reader
description
Implements WCAG 2.2 AA color contrast (4.5:1 text, 3:1 UI), semantic HTML landmarks, heading hierarchy, table markup, ARIA naming, live regions, and screen reader optimization for accessible web applications.
license
MIT
compatibility
opencode
metadata
{"version":"1.0.0","domain":"coding","role":"implementation","scope":"implementation","output-format":"code","triggers":"color contrast, wcag accessibility, screen reader optimization, aria labels, semantic html, landmark navigation, heading hierarchy, alt text","related-skills":[],"archetypes":"tactical, diagnostic","anti_triggers":"brainstorming, vague ideation","response_profile":{"verbosity":"low","directive_strength":"high","abstraction_level":"operational"}}
# WCAG 2.2 AA Color Contrast & Screen Reader Optimization Implement color contrast ratios (4.5:1 minimum for normal text, 3:1 for large text and UI components) and semantic HTML structure with ARIA attributes to ensure WCAG 2.2 AA compliance for assistive technology users. ## TL;DR Checklist - [ ] Color contrast verified: 4.5:1 for body text, 3:1 for large text, 3:1 for UI components (WAVE, Axe, Lighthouse) - [ ] Semantic HTML: one `<main>`, `<nav>`, `<header>`, `<footer>`, `<aside>` per page (landmarks) - [ ] Heading hierarchy: `<h1>` once per page, no skipped levels (h1 → h2 → h3, never h1 → h3) - [ ] Tables marked correctly: `<th scope="col|row">`, `<caption>`, `headers` attribute on complex tables - [ ] Icons: `aria-label` on `<span>` icons or alt text on `<img>`; meaningful, not "icon" or "image" - [ ] ARIA naming: follows order (aria-label > aria-labelledby > text content) - [ ] Live regions: `aria-live="polite"` for non-urgent updates, `aria-live="assertive"` for alerts - [ ] Status messages: `role="status"` for messages that should be announced - [ ] Screen reader tested: VoiceOver (macOS), NVDA (Windows), or JAWS --- ## When to Use Use this skill when: - Building or reviewing components that must pass WCAG 2.2 AA conformance - Designing color palettes or applying brand colors to UI - Implementing form controls, buttons, links, or icon-based interactions - Creating data tables, lists, or complex layouts - Building live update regions (notifications, search results, form validation) - Working with screen readers (VoiceOver, NVDA, JAWS) in testing - Retrofitting existing applications to meet accessibility standards - Ensuring color alone does not convey critical information --- ## When NOT to Use Avoid this skill for: - WCAG 2.1 AAA (enhanced contrast 7:1) requirements — that's a separate, stricter standard - Automated color science or color theory deep dives — focus here is accessibility thresholds - Screen reader automation or third-party testing integrations (use Axe, WAVE, Pa11y for those) - PDFs or document accessibility (different standards apply — see PDF/UA) - Video captions or audio descriptions (separate WCAG criteria: 1.2.1, 1.2.2) - Mobile-only app accessibility (native mobile guidelines may differ) --- ## Core Workflow ### 1. Calculate & Verify Color Contrast **Checkpoint:** Before applying any color, measure its contrast ratio against backgrounds and adjacent colors. **Formula:** Contrast Ratio = (L1 + 0.05) / (L2 + 0.05), where L = relative luminance - L = 0.2126 × R + 0.7152 × G + 0.0722 × B (linear RGB 0–1) - If color channel > 0.03928: channel = channel^2.4; else: channel / 12.92 **WCAG 2.2 AA Thresholds:** - **Normal text**: 4.5:1 (body copy, labels, any text < 18px or < 14px bold) - **Large text**: 3:1 (text ≥ 18px or ≥ 14px bold) - **UI components**: 3:1 (buttons, form inputs, borders, focus indicators) - **Icons/graphics**: 3:1 (if conveying information) **Manual Testing (when tool results are unclear):** - Contrast over gradients: Must test the darkest/lightest pixel pair - Contrast with images: Must test lightest + darkest image regions - Hover/focus states: Must meet 3:1 (for non-text contrast) with adjacent color **Tools:** [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/), [Axe DevTools](https://www.deque.com/axe/devtools/), [WAVE](https://wave.webaim.org/), [Lighthouse](https://developers.google.com/web/tools/lighthouse) ### 2. Define Color Tokens with Contrast Built-In **Checkpoint:** Create a color palette where every color variant is paired with minimum contrast text color. All colors in your design system should specify: "This color is ONLY for backgrounds" or "This color is ONLY for text at 4.5:1 on Color X." **Design pattern:** Use `isAccessibleOnBackground()` function or lookup tables to prevent misuse. ### 3. Structure Semantic HTML Landmarks **Checkpoint:** Every page must have exactly one `<main>`, and navigation must be wrapped in `<nav>`. Landmarks allow screen reader users to jump past content: - `<header>` — top banner (logo, title, global nav) - `<nav>` — navigation menu (one per type: main nav, footer nav, sidebar nav) - `<main>` — primary content (one per page) - `<aside>` — tangential content (sidebar, related articles) - `<footer>` — site footer (copyright, links) ### 4. Verify Heading Hierarchy **Checkpoint:** Page starts with `<h1>`, no levels skipped (h1 → h2 → h3, never h1 → h3). Each section must have a heading that announces its topic. Use `<h2>` to start subsections, not `<h3>`. ### 5. Mark Tables Semantically **Checkpoint:** Header cells use `<th scope="col|row">`, data cells use `<td>`. For complex tables: add `id` to headers and `headers` attribute on data cells pointing to multiple headers. ### 6. Label Icons & Images Meaningfully **Checkpoint:** Every icon and image has an `aria-label` or `alt` text that describes its function, not its appearance. Example: ❌ `aria-label="settings icon"` | ✅ `aria-label="account settings"` ### 7. Implement Live Regions for Updates **Checkpoint:** Dynamic content (form validation results, search updates, notifications) must announce to screen readers. Use `aria-live="polite"` for non-urgent updates, `aria-live="assertive"` for urgent alerts. ### 8. Test with Screen Readers **Checkpoint:** Before shipping, test with at least one screen reader: VoiceOver (macOS, iOS), NVDA (Windows), or JAWS (Windows). Read the page top-to-bottom, verify: landmarks are announced, headings make sense, form labels are read, icons are understood, live updates are heard. --- ## Implementation Patterns ### Pattern 1: CSS Color Tokens with Contrast Metadata ```typescript // colors.ts — Design tokens with built-in accessibility guarantees interface ColorToken { hex: string; name: string; luminance: number; // L from contrast formula textColor: "light" | "dark"; // Which text color meets 4.5:1 minContrastRatio: number; // Verified minimum ratio } const colors = { neutral50: { hex: "#F9FAFB", name: "Neutral 50", luminance: 0.98, textColor: "dark", // Use dark text (e.g., #1F2937) minContrastRatio: 12.6, }, neutral900: { hex: "#111827", name: "Neutral 900", luminance: 0.015, textColor: "light", // Use light text (e.g., #F9FAFB) minContrastRatio: 15.5, }, blue500: { hex: "#3B82F6", name: "Blue 500", luminance: 0.18, textColor: "light", // White text at 4.5:1+ minContrastRatio: 5.2, }, red500: { hex: "#EF4444", name: "Red 500", luminance: 0.213, textColor: "light", // Light text for error states minContrastRatio: 4.7, }, } as const; // Helper: Ensure color is used safely function getTextColorForBackground(bgToken: ColorToken): string { const textColor = bgToken.textColor === "light" ? "#FFFFFF" : "#1F2937"; if (bgToken.minContrastRatio < 4.5) { console.warn( `⚠️ Color ${bgToken.name} has only ${bgToken.minContrastRatio.toFixed(2)}:1 contrast. Consider using a darker background.` ); } return textColor; } // Usage: Safe color application const buttonBg = colors.blue500; const buttonText = getTextColorForBackground(buttonBg); // Result: buttonText = "#FFFFFF" (guaranteed 5.2:1 contrast) ``` **Why This Pattern:** - Contrast is verified once (at token definition), then reused everywhere - No designer can accidentally pair a 2:1 contrast color combination - Warnings catch misuse at runtime --- ### Pattern 2: Semantic HTML Page Structure with Landmarks ```html <!-- Complete WCAG 2.2 AA page structure --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Product Dashboard — MyApp</title> </head> <body> <!-- LANDMARK 1: Header with branding --> <header role="banner" aria-label="Site header"> <div class="header-content"> <a href="/" class="logo" aria-label="MyApp home"> <img src="logo.svg" alt="MyApp" /> </a> <!-- LANDMARK 2: Primary navigation --> <nav aria-label="Main navigation"> <ul> <li> <a href="/dashboard" aria-current="page">Dashboard</a> </li> <li><a href="/analytics">Analytics</a></li> <li><a href="/settings">Settings</a></li> </ul> </nav> </div> </header> <div class="page-layout"> <!-- LANDMARK 3: Sidebar navigation (secondary) --> <aside aria-label="Sidebar navigation"> <nav aria-label="Filters"> <fieldset> <legend>Filter by status</legend> <label> <input type="checkbox" name="status" value="active" /> Active </label> <label> <input type="checkbox" name="status" value="pending" /> Pending </label> </fieldset> </nav> </aside> <!-- LANDMARK 4: Main content area (only one per page) --> <main id="main-content" aria-label="Dashboard content"> <!-- Section with heading hierarchy --> <h1>Sales Dashboard</h1> <!-- Key metrics section --> <section aria-labelledby="metrics-heading"> <h2 id="metrics-heading">Q4 Metrics</h2> <!-- Grid of metric cards with proper ARIA --> <div class="metrics-grid"> <article class="metric-card"> <h3>Total Revenue</h3> <p class="metric-value" aria-label="Total revenue: 124 thousand dollars"> $124K </p> <p class="metric-change" aria-label="increase of 12 percent"> ↑ 12% </p> </article> <article class="metric-card"> <h3>Active Users</h3> <p class="metric-value" aria-label="Active users: 3 thousand 420"> 3.4K </p> <p class="metric-change" aria-label="increase of 8 percent"> ↑ 8% </p> </article> </div> </section> <!-- Data table with accessibility markup --> <section aria-labelledby="table-heading"> <h2 id="table-heading">Recent Orders</h2> <table> <caption>Orders from the past 7 days, sorted by date</caption> <thead> <tr> <th scope="col">Order ID</th> <th scope="col">Customer</th> <th scope="col">Total</th> <th scope="col">Status</th> <th scope="col">Action</th> </tr> </thead> <tbody> <tr> <td>ORD-001</td> <td>Alice Smith</td> <td>$2,500</td> <td> <span class="badge badge-completed" role="status" aria-label="Completed" > Completed </span> </td> <td> <button aria-label="View order ORD-001 details">View</button> </td> </tr> <tr> <td>ORD-002</td> <td>Bob Johnson</td> <td>$1,200</td> <td> <span class="badge badge-pending" role="status" aria-label="Pending" > Pending </span> </td> <td> <button aria-label="View order ORD-002 details">View</button> </td> </tr> </tbody> </table> </section> <!-- Live region for dynamic updates --> <div id="search-results" aria-live="polite" aria-label="Search results" role="status" > <!-- JavaScript updates this area; screen readers announce changes --> </div> </main> </div> <!-- LANDMARK 5: Footer --> <footer role="contentinfo" aria-label="Site footer"> <nav aria-label="Footer navigation"> <ul> <li><a href="/privacy">Privacy Policy</a></li> <li><a href="/terms">Terms of Service</a></li> <li><a href="/accessibility">Accessibility</a></li> </ul> </nav> <p>&copy; 2026 MyApp, Inc. All rights reserved.</p> </footer> </body>
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen