Building Accessible Color Palettes
Why Accessibility and Color Must Coexist
An estimated 300 million people worldwide have color vision deficiency. Millions more have low vision or age-related visual decline. If your color palette doesn't provide sufficient contrast, a significant portion of your audience simply can't read your content.
Accessibility isn't a constraint on design — it's a design skill. The best accessible palettes are indistinguishable from good design to sighted users, but they unlock your product for everyone else.
WCAG Contrast Requirements
The Web Content Accessibility Guidelines define two levels of contrast compliance:
| Level | Normal Text | Large Text | UI Components |
|---|---|---|---|
| AA (minimum) | 4.5:1 | 3:1 | 3:1 |
| AAA (enhanced) | 7:1 | 4.5:1 | — |
Large text is defined as 18pt (24px) or 14pt (18.66px) bold. Everything else counts as normal text.
UI components include form fields, buttons, icons, and focus indicators. They need at least 3:1 contrast against adjacent colors.
Contrast Ratio Basics
The contrast ratio compares the relative luminance of two colors:
- 1:1 — No contrast (same color)
- 3:1 — Minimum for large text and UI elements
- 4.5:1 — Minimum for normal text (AA)
- 7:1 — Enhanced readability (AAA)
- 21:1 — Maximum (black on white)
Building a Palette That Scales
Step 1: Start with Neutral Tones
Create a gray scale that maps to semantic roles. Each step should have at least 4.5:1 contrast against adjacent steps for text usage.
| Token | Hex | Use | Contrast on White |
|---|---|---|---|
gray-900 | #111827 | Primary text | 17.4:1 |
gray-700 | #374151 | Secondary text | 9.3:1 |
gray-500 | #6b7280 | Placeholder text | 4.6:1 |
gray-300 | #d1d5db | Borders, dividers | 1.6:1 (decorative) |
gray-100 | #f3f4f6 | Backgrounds | 1.1:1 (background) |
Step 2: Add Brand Colors with Contrast Pairs
For each brand color, define both a background shade and a text-on-background shade that meets 4.5:1 contrast.
:root {
--blue-500: #3b82f6; /* Brand primary */
--blue-600: #2563eb; /* Accessible text on light bg */
--blue-100: #dbeafe; /* Light background */
}
/* Blue-600 on white = 4.6:1 (AA pass) */
/* White on blue-600 = 4.6:1 (AA pass) */
/* Blue-500 on white = 3.8:1 (AA fail for normal text) */
Notice that blue-500 fails AA for normal text on white. Many popular brand colors do. The fix: use a darker shade for text and keep the lighter shade for decorative or large-text use.
Step 3: Define Semantic Colors
Semantic colors signal meaning and must be distinguishable from each other, especially for users with color vision deficiency:
| Meaning | Color | Accessible Shade | Pair With |
|---|---|---|---|
| Success | Green | #15803d | White text: 5.4:1 |
| Warning | Amber | #b45309 | White text: 4.7:1 |
| Error | Red | #dc2626 | White text: 4.6:1 |
| Info | Blue | #1d4ed8 | White text: 8.6:1 |
Never rely on color alone to convey meaning. Pair every semantic color with an icon or text label so colorblind users can distinguish states.
Dark Mode Contrast
Dark mode inverts the contrast challenge. You're not making dark text readable on light backgrounds — you're making light text readable on dark ones.
Common dark mode mistakes:
- Pure black backgrounds:
#000000creates too harsh a contrast with white text (21:1), causing eye strain. Use#111827or#1f2937instead. - Desaturated colors: Brand colors that work on white often appear to "vibrate" on dark backgrounds. Reduce saturation by 10–20% for dark mode variants.
- Low-contrast borders:
gray-700borders ongray-900backgrounds often fail 3:1. Test explicitly.
.dark {
--bg-primary: #111827;
--text-primary: #f9fafb; /* Contrast: 17.4:1 */
--text-secondary: #d1d5db; /* Contrast: 12.5:1 */
--text-placeholder: #9ca3af; /* Contrast: 7.1:1 */
--border: #374151; /* Contrast: 2.3:1 (decorative only) */
}
Testing Your Palette
Automated Tools
- Browser DevTools: Chrome and Firefox show contrast ratios in the color picker
- axe DevTools: Scans entire pages for WCAG violations
- Adobe Color: Accessibility tools for palette design
Manual Testing Checklist
- All text meets 4.5:1 contrast against its background
- Large text and UI elements meet 3:1 contrast
- Semantic colors are distinguishable under color vision deficiency simulation
- Focus indicators meet 3:1 contrast against adjacent colors
- Dark mode meets the same contrast thresholds
- Link text is distinguishable from surrounding body text (not just by color)
Related Guides
Try It Yourself
Build accessible color palettes with live contrast checking. Our tool shows WCAG compliance for every color pair as you design.