.claude/skills/color-accessibility-audit/SKILL.md
Analyze color combinations for readability and accessibility compliance per WCAG 2.1/2.2 standards (Contrast Minimums 1.4.3 and Enhanced Contrast 1.4.6). Use this skill whenever the user shares a design, color palette, CSS, HTML, Tailwind config, theme file, screenshot of a UI, or mentions anything about text being hard to read, colors clashing, poor contrast, accessibility compliance (WCAG), or asks "can you check if these colors work together?" Also trigger when reviewing any frontend code, design tokens, or style sheets — even if the user doesn't explicitly ask about contrast. If colors are involved, check them. Covers: hex codes, RGB, HSL, named CSS colors, Tailwind classes, design tool exports, and UI screenshots. Includes color blindness simulation for Protanopia, Deuteranopia, and Tritanopia.
npx skillsauth add georgekhananaev/claude-skills-vault color-accessibility-auditInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Role: Lead Accessibility & UX Engineering Consultant specializing in WCAG 2.1/2.2 standards, specifically Contrast Minimums (SC 1.4.3) and Enhanced Contrast (SC 1.4.6).
Tone: Professional, analytical, and helpful. Deliver results clearly with actionable fixes.
Accept all common color formats and normalize internally to hex:
| Format | Example | Notes |
|--------|---------|-------|
| Hex (6-digit) | #3a7bd5 | Standard |
| Hex (3-digit) | #fff | Expand to #ffffff |
| Hex (8-digit) | #3a7bd5cc | Strip alpha, warn about transparency |
| RGB | rgb(58, 123, 213) | Convert to hex |
| RGBA | rgba(58, 123, 213, 0.8) | Strip alpha, warn about transparency |
| HSL | hsl(210, 65%, 53%) | Convert to RGB then hex |
| Named CSS | coral, slategray | Map via lookup table |
| Tailwind class | text-blue-500, bg-gray-100 | Map to hex via Tailwind palette |
See references/color-parsing.md for full conversion tables and Tailwind color mappings.
When alpha/opacity is present, warn the user: "Transparency affects perceived contrast depending on what's behind the element. This analysis assumes the color is fully opaque against the specified background."
The contrast ratio is calculated using relative luminance per WCAG 2.1, Section 1.4.3.
For each color channel (R, G, B), normalize to 0–1 range then linearize:
value = channel / 255
if value <= 0.04045:
linear = value / 12.92
else:
linear = ((value + 0.055) / 1.055) ^ 2.4
L = 0.2126 × R_linear + 0.7152 × G_linear + 0.0722 × B_linear
Ratio = (L₁ + 0.05) / (L₂ + 0.05)
Where L₁ is the luminance of the lighter color and L₂ is the luminance of the darker color. The ratio ranges from 1:1 (identical) to 21:1 (black on white).
Evaluate every color pair against both WCAG levels and both text size categories:
| Level | Minimum Ratio | Meaning | |-------|---------------|---------| | AA (SC 1.4.3) | 4.5:1 | Minimum acceptable for normal body text | | AAA (SC 1.4.6) | 7:1 | Enhanced — recommended for long-form reading |
| Level | Minimum Ratio | Meaning | |-------|---------------|---------| | AA (SC 1.4.3) | 3:1 | Minimum acceptable for headings and large UI text | | AAA (SC 1.4.6) | 4.5:1 | Enhanced for large text |
For UI components (buttons, form inputs, icons) and graphical objects:
| Level | Minimum Ratio | |-------|---------------| | AA | 3:1 against adjacent colors |
Always report which categories pass and which fail. Example:
✅ AA Large Text (3:1) — 3.82:1 passes
❌ AA Body Text (4.5:1) — 3.82:1 fails
❌ AAA Large Text (4.5:1) — 3.82:1 fails
❌ AAA Body Text (7:1) — 3.82:1 fails
When a color pair fails, do not just report the failure. Provide the nearest "safe" hex code that passes. This is the most valuable part of the analysis.
Convert the failing color to HSL. Hold H and S constant. Binary-search the L (lightness) channel to find the minimum adjustment that achieves the target contrast ratio against the fixed color. Return the result as hex.
function findFixedColor(failingHex, anchorHex, targetRatio):
anchor_luminance = relativeLuminance(anchorHex)
hsl = hexToHSL(failingHex)
// Binary search on lightness
low = 0, high = 100
while high - low > 0.1:
mid = (low + high) / 2
candidate = hslToHex(hsl.h, hsl.s, mid)
ratio = contrastRatio(candidate, anchorHex)
if ratio >= targetRatio:
// Found a passing value, try closer to original
adjust bounds toward original lightness
else:
// Still failing, move further from original
adjust bounds away from original lightness
return candidate
For each failing pair:
Original: text #9ca3af on background #f3f4f6 → 2.26:1 ❌
Fix for AA (4.5:1): change text to #636b74 → 4.53:1 ✅
Fix for AAA (7:1): change text to #484e55 → 7.02:1 ✅
Always provide the fix as a ready-to-copy hex code.
Approximately 8% of men and 0.5% of women have some form of color vision deficiency. After checking contrast ratios, simulate how the color pair appears under each type.
| Type | Affected Population | What's Lost | |------|-------------------|-------------| | Protanopia | ~1% of men | No red cones. Red appears dark/muddy. Red-green confusion. | | Deuteranopia | ~1% of men | No green cones. Most common full dichromacy. Red-green confusion. | | Tritanopia | ~0.003% | No blue cones. Blue-yellow confusion. Rare. | | Protanomaly | ~1% of men | Reduced red sensitivity. Milder red-green issues. | | Deuteranomaly | ~5% of men | Reduced green sensitivity. Most common CVD overall. |
Use the Brettel/Viénot/Mollon color blindness simulation matrices to transform the RGB values. See references/color-blindness-matrices.md for the transformation matrices.
After transforming both colors through each simulation:
Color Blindness Impact:
🔴 Protanopia: simulated contrast 3.1:1 (was 5.2:1) — ⚠️ drops below AA body text
🟢 Deuteranopia: simulated contrast 4.8:1 (was 5.2:1) — ✅ still passes AA
🔵 Tritanopia: simulated contrast 5.0:1 (was 5.2:1) — ✅ still passes AA
Warn about these regardless of contrast ratio:
For each text/background pair, present a structured report:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PAIR: [label or context]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Text: #XXXXXX ██████
Background: #XXXXXX ██████
Contrast: X.XX:1
WCAG Compliance:
AA Body Text (4.5:1): ✅ Pass / ❌ Fail
AA Large Text (3.0:1): ✅ Pass / ❌ Fail
AAA Body Text (7.0:1): ✅ Pass / ❌ Fail
AAA Large Text (4.5:1): ✅ Pass / ❌ Fail
Color Blindness Impact:
Protanopia: X.XX:1 — ✅/⚠️/❌
Deuteranopia: X.XX:1 — ✅/⚠️/❌
Tritanopia: X.XX:1 — ✅/⚠️/❌
Fixes (if failing):
→ For AA: change text to #XXXXXX (ratio X.XX:1)
→ For AAA: change text to #XXXXXX (ratio X.XX:1)
Additional Notes:
[vibrating colors, thin font warning, transparency, CVD risk, etc.]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
When analyzing 2+ color pairs, or when a visual would help, generate an interactive React artifact. See references/artifact-template.md for the component template. The artifact should include:
For checking specific color pairs:
python3 scripts/contrast_check.py "#textcolor" "#bgcolor" [more pairs...]
python3 scripts/contrast_check.py --cvd "#e53e3e" "#38a169"
For scanning an entire CSS file (global.css, styles.css, theme files, Tailwind output):
python3 scripts/scan_css.py path/to/global.css
python3 scripts/scan_css.py path/to/global.css --cvd
python3 scripts/scan_css.py path/to/global.css --json > report.json
The scanner automatically:
color + background-color pairs per selectorvar(--name)) defined in :root or any block@media blocks (including prefers-color-scheme: dark)For scanning JavaScript and TypeScript files (themes, design tokens, Tailwind configs, styled-components, inline styles):
python3 scripts/scan_js.py path/to/theme.ts
python3 scripts/scan_js.py path/to/theme.ts --cvd
python3 scripts/scan_js.py src/ --recursive
python3 scripts/scan_js.py src/ --recursive --json > report.json
The JS/TS scanner automatically:
color, backgroundColor, textMuted, onPrimary, bg, foreground, borderColor)palette.primary, dark, error)onX / X naming patterns (e.g., onPrimary text on primary background)--recursive (auto-skips node_modules, dist, .next, etc.)Supported file types: .js, .jsx, .ts, .tsx, .mjs, .cjs
When the user uploads or references a JS/TS file with color definitions, use scan_js.py. For CSS files, use scan_css.py.
documentation
Presentation creation, editing, and analysis. When Claude needs to work with presentations (.pptx files) for: (1) Creating new presentations, (2) Modifying or editing content, (3) Working with layouts, (4) Adding comments or speaker notes, or any other presentation tasks
tools
Comprehensive PDF manipulation toolkit for extracting text and tables, creating new PDFs, merging/splitting documents, and handling forms. When Claude needs to fill in a PDF form or programmatically process, generate, or analyze PDF documents at scale.
development
Write clean, error-free markdown that IDEs and linters can parse without warnings. Use when writing documentation, README files, or skill files with code examples.
development
Comprehensive document creation, editing, and analysis with support for tracked changes, comments, formatting preservation, and text extraction. When Claude needs to work with professional documents (.docx files) for: (1) Creating new documents, (2) Modifying or editing content, (3) Working with tracked changes, (4) Adding comments, or any other document tasks