WCAG Contrast Ratios
WCAG (Web Content Accessibility Guidelines) defines minimum contrast ratios
- AA (minimum): 4.5:1 for normal text, 3:1 for large text (18px+ or bold 14px+).
- AAA (enhanced): 7:1 for normal text, 4.5:1 for large text.
Most products aim for AA compliance. AAA is recommended for high-contrast themes or government sites.
### Checking Contrast
Use a contrast checker
- Figma A11y Plugin: Select text, check contrast against background.
- Color.Ninja: Paste colors, see contrast ratio.
- WebAIM Contrast Checker: webaim.org/resources/contrastchecker/.
Example
- Pass AA: `#3B6DFF` (text) on `#FFFFFF` (background) = 4.51:1 ✓
- Fail AA: `#6EE7B7` (text) on `#FFFFFF` (background) = 1.78:1 ✗
If a color fails, darken text or lighten background until it passes.
Building a Tonal Scale
Don't pick one blue and call it a palette. Build a tonal scale: 5–9 steps from near-black to near-white, tinted toward your brand hue.
### Example: Cyan Tonal Scale
```
cyan-50: #E0F7FA (background, hover states)
cyan-100: #B2EBF2
cyan-200: #80DEEA
cyan-300: #4DD0E1
cyan-400: #26C6DA
cyan-500: #00BCD4 (primary, base)
cyan-600: #00ACC1
cyan-700: #0097A7 (text on light backgrounds)
cyan-800: #00838F
cyan-900: #006064 (text, high contrast)
```
This gives you options: `cyan-500` for buttons, `cyan-700` for text on white, `cyan-900` for high-contrast text.
### Perceptual Uniformity
RGB space is not perceptually uniform. A jump from `#0000FF` to `#0000CC` looks different than `#FF0000` to `#CC0000`. Use LAB color space for perceptually uniform scales.
Tools
- Figma Palette Plugin: Generates perceptually uniform scales.
- Leonardo (Adobe): leonardocolor.io. Creates accessible, perceptually uniform palettes.
- Coolors: coolors.co. Quick palette generation with contrast checks.
These tools ensure each step in your scale has consistent perceived lightness.
Colorblind Simulation
8% of men and 0.5% of women have color vision deficiency. Three common types
- Deuteranopia: Red-green confusion (most common).
- Protanopia: Similar to Deuteranopia, but red is darker.
- Tritanopia: Blue-yellow confusion (rare).
### Testing Your Palette
Use colorblind simulators
- Figma Stark Plugin: Simulate colorblindness in Figma. See how your design looks to colorblind users.
- Color Oracle: colororacle.org. Desktop app that simulates colorblindness across your entire screen.
- Chrome DevTools: Open DevTools > Rendering > Emulate vision deficiencies.
### Fixing Colorblind Issues
Don't rely on color alone to convey information. Examples
Bad: Green button = success, red button = error (colorblind users can't distinguish).
Good: Green button + checkmark icon = success, red button + X icon = error. Color + icon/text ensures clarity.
Bad: Red line and green line on a chart (colorblind users see two similar lines).
Good: Red solid line and green dashed line. Pattern + color ensures distinction.
Exporting Palettes to Design Systems
Once your palette is finalized, export it as JSON, CSS, or SCSS.
### JSON Export
```json {
"colors": {
"primary": {
"50": "#E0F7FA",
"500": "#00BCD4",
"700": "#0097A7",
"900": "#006064"
},
"background": {
"default": "#0A0D12",
"card": "#0F131C",
"elevated": "#161D2B"
},
"text": {
"primary": "#FFFFFF",
"secondary": "#A0A4A8",
"muted": "#6B7280"
} } } ```
### CSS Variables
```css :root {
--color-primary-50: #E0F7FA;
--color-primary-500: #00BCD4;
--color-primary-700: #0097A7;
--color-primary-900: #006064;
--color-background-default: #0A0D12;
--color-background-card: #0F131C;
--color-text-primary: #FFFFFF;
--color-text-secondary: #A0A4A8;
} ```
### SCSS Variables
```scss
$color-primary-50: #E0F7FA;
$color-primary-500: #00BCD4;
$color-primary-700: #0097A7;
$color-primary-900: #006064;
$color-background-default: #0A0D12;
$color-background-card: #0F131C;
$color-text-primary: #FFFFFF;
$color-text-secondary: #A0A4A8;
```
Use a tool like Style Dictionary to automate conversion
```bash # Install npm install -g style-dictionary
# Build style-dictionary build --config config.json ```
Naming Color Tokens
Avoid literal names (`blue-500`). Use semantic names
- Good: `--color-primary`, `--color-background`, `--color-text-primary`
- Bad: `--blue-500`, `--gray-800`, `--cyan-700`
Semantic names let you swap colors without renaming every variable. If you rebrand from blue to purple, `--color-primary` stays the same; only its value changes.
Testing Accessibility
Before launch
- Contrast check: All text passes WCAG AA (4.5:1 for normal, 3:1 for large).
- Colorblind simulation: Test with Stark or Color Oracle. Ensure critical UI is distinguishable.
- Automated audit: Run Lighthouse or Axe DevTools. Fix reported color contrast issues.
- Manual review: Navigate the site without color. Can you tell success from error? If not, add icons/labels.
Accessible color palettes ensure everyone can use your product, regardless of vision.