The short answer
Accessible color is not a separate concern you bolt on at the end - it is the difference between a design that works for everyone and one that works for people with your eyesight, your screen, and your lighting. The single most important measure is contrast: how distinct foreground is from background. Get contrast right and most of accessibility follows.
Contrast and WCAG
The Web Content Accessibility Guidelines (WCAG) define contrast as a ratio between two colors, from 1:1 (identical) to 21:1 (black on white). The thresholds that matter:
- 4.5:1 - normal body text, to meet level AA.
- 3:1 - large text (roughly 24px+, or 19px+ bold) and meaningful UI elements like icons and input borders.
- 7:1 - the stricter AAA level for body text, worth aiming for on reading-heavy screens.
These are not suggestions in most contexts - accessibility law in many countries references WCAG AA directly.
Never color alone
Roughly 8% of men and 0.5% of women have some form of color vision deficiency. If the only thing separating "error" from "success" is red versus green, those users see two identical grays.
- Pair color with an icon, a label, or a shape - a red field with an alert icon and text, not just a red border.
- Do not use color as the sole indicator of state, selection, or meaning.
- Test your screens through a colorblindness simulator - most design tools have one built in.
Dark mode
Dark mode is not an inverted light theme. Pure white text on pure black vibrates and fatigues the eye; pure-black shadows disappear. Doing it well means:
- Soften the extremes. Off-white text (not #fff) on a dark gray (not #000) reads more comfortably.
- Rethink elevation. In light mode shadows show depth; in dark mode, lighter surfaces do. A raised card is a slightly lighter gray.
- Desaturate. Saturated colors glow uncomfortably on dark backgrounds - pull them back and re-check contrast, which behaves differently against dark.
This is exactly where semantic tokens pay off: color.text.primary is one value in light mode and another in dark, and every screen follows.
An accessible palette
Build the palette as tested pairs, not isolated swatches. A color is not "accessible" on its own - only against the background it sits on. Decide the background/foreground combinations up front, verify each meets the ratio, and store them as tokens so nobody hand-picks an untested pair later.
Checking your work
- Contrast checkers (WebAIM, or the one built into Figma and browser devtools) give you the exact ratio for any pair.
- Browser DevTools flag low-contrast text and simulate vision deficiencies.
- Test in real conditions - a phone at minimum brightness, outdoors. The lab is not where your users read.