Color Accessibility — WCAG Contrast Ratios and Tools
WCAG 2.1 requires a 4.5:1 contrast ratio for normal text and 3:1 for large text. Learn how to calculate contrast ratios, test color combinations, use browser DevTools, and...
Use the tool
Color Picker
Pick colors, convert hex/RGB/HSL/OKLCH, and check WCAG contrast.
Color contrast affects readability for everyone — especially for people with low vision or color blindness. WCAG 2.1 defines minimum contrast ratios that every public website should meet.
Use the Color Picker to check color values and plan accessible color pairs.
WCAG contrast requirements
| Level | Text type | Minimum ratio |
|---|---|---|
| AA | Normal text (< 18pt regular, < 14pt bold) | 4.5:1 |
| AA | Large text (≥ 18pt regular or ≥ 14pt bold) | 3:1 |
| AA | UI components, graphics | 3:1 |
| AAA | Normal text | 7:1 |
| AAA | Large text | 4.5:1 |
- “pt” here means CSS pixels — 18pt = 24px, 14pt = ~18.67px bold
- Decorative images and disabled UI elements are exempt
How contrast ratio is calculated
function getLuminance(hexColor) {
const rgb = hexToRgb(hexColor);
const [r, g, b] = [rgb.r, rgb.g, rgb.b].map(c => {
const srgb = c / 255;
return srgb <= 0.04045
? srgb / 12.92
: Math.pow((srgb + 0.055) / 1.055, 2.4);
});
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
function contrastRatio(hex1, hex2) {
const l1 = getLuminance(hex1);
const l2 = getLuminance(hex2);
const lighter = Math.max(l1, l2);
const darker = Math.min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
function hexToRgb(hex) {
const clean = hex.replace('#', '');
return {
r: parseInt(clean.slice(0, 2), 16),
g: parseInt(clean.slice(2, 4), 16),
b: parseInt(clean.slice(4, 6), 16),
};
}
// Test common combinations:
contrastRatio('#ffffff', '#000000') // 21:1 (maximum)
contrastRatio('#ffffff', '#767676') // 4.54:1 (just passes AA)
contrastRatio('#ffffff', '#949494') // 2.85:1 (fails AA)
contrastRatio('#ffffff', '#6366f1') // ~3.7:1 (fails AA for normal text)
Check common color pairs
function getWcagLevel(hex1, hex2, isLargeText = false) {
const ratio = contrastRatio(hex1, hex2);
const aa = isLargeText ? 3 : 4.5;
const aaa = isLargeText ? 4.5 : 7;
return {
ratio: Math.round(ratio * 100) / 100,
passAA: ratio >= aa,
passAAA: ratio >= aaa,
level: ratio >= aaa ? 'AAA' : ratio >= aa ? 'AA' : 'Fail',
};
}
// Example results:
getWcagLevel('#1e293b', '#ffffff') // { ratio: 16.1, passAA: true, level: 'AAA' }
getWcagLevel('#6366f1', '#ffffff') // { ratio: 3.7, passAA: false, level: 'Fail' }
getWcagLevel('#6366f1', '#1e1b4b') // { ratio: 4.7, passAA: true, level: 'AA' }
Common failing combinations
White text on colored backgrounds (often fail):
- #ff0000 (red) on white: 4.0:1 (FAILS for normal text)
- #0000ff (blue) on white: 8.6:1 (passes)
- #008000 (green) on white: 4.1:1 (FAILS for normal text)
- #ff6600 (orange) on white: 2.9:1 (FAILS)
- #6366f1 (Indigo-500) on white: 3.7:1 (FAILS)
Use these instead:
- Indigo-700 (#4338ca) on white: 6.3:1 (PASSES AA)
- Red-700 (#b91c1c) on white: 5.9:1 (PASSES AA)
- Green-700 (#15803d) on white: 4.6:1 (PASSES AA)
Tailwind accessible color guide
// Tailwind palette: which shades pass AA on white/black?
// On WHITE background (need 4.5:1+):
// Slate-600 and darker: #475569+ (5.1:1) ✓
// Indigo-700 and darker: #4338ca (6.3:1) ✓
// Red-700 and darker: #b91c1c (5.9:1) ✓
// On BLACK background (need 4.5:1+):
// Slate-300 and lighter: #cbd5e1 (7.0:1) ✓
// Indigo-300 and lighter: #a5b4fc (6.7:1) ✓
CSS: WCAG-compliant text on variable backgrounds
/* Light/dark mode that maintains contrast: */
:root {
--bg: #ffffff;
--text: #1e293b; /* 16:1 contrast on white */
--accent: #4338ca; /* Indigo-700: 6.3:1 on white */
--muted: #64748b; /* Slate-500: 4.6:1 on white — borderline AA */
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #0f172a;
--text: #f8fafc; /* 18:1 contrast on dark bg */
--accent: #818cf8; /* Indigo-400: 5.1:1 on dark bg */
--muted: #94a3b8; /* Slate-400: 5.9:1 on dark bg */
}
}
Test in browser DevTools
Chrome DevTools → Inspect element → Click color swatch → Shows contrast ratio with ✓ or ✗ for WCAG AA/AAA.
Firefox → Accessibility panel → Show contrast for any element.
Related tools
- Color Picker — pick colors and convert formats
- Color Theory for Web — color harmony and theory
- HEX, RGB, HSL Conversion — color format guide
Related posts
- WCAG Contrast Explained (AA vs AAA, When It Matters) — Color contrast determines who can read your interface. This is the WCAG math, th…
- Hex, RGB, HSL, OKLCH: Which to Pick in 2026 — Four CSS color formats, four different audiences. This is what each is good at, …
- Color Palette Generator — Build Color Palettes from a Base Color — A color palette generator creates coordinated color sets from a single base colo…
- Color Picker Tools — Browser DevTools, VS Code, and Online Pickers — Color picker tools help designers and developers find and manage colors. Learn h…
- Color Theory for Web Design — Hue, Saturation, and Color Harmonies — Color theory explains how colors relate to each other and why some combinations …
Related tool
Color Picker
Pick colors, convert hex/RGB/HSL/OKLCH, and check WCAG contrast.
Written by Mian Ali Khalid. Part of the Frontend & Design pillar.