Skip to main content
Guide Design & foundations

Color and contrast that actually works

Accessible color is not a matter of taste. Every pair of colors on a screen has a measurable contrast ratio, and WCAG sets the exact minimum it needs to clear, for body text, for buttons and icons, and for anything that should never depend on color alone.

Reference13 min readLast verified August 2026

What you’ll learn

  • Explain what a WCAG contrast ratio actually measures, and why it runs from 1:1 to 21:1.
  • Apply the correct AA minimum, 4.5:1 for text or 3:1 for large text and UI components, instead of guessing.
  • Spot when a design relies on color alone to convey meaning, and fix it before it fails 1.4.1.
  • Build a palette by role (background, text, accent) instead of picking hues that just look nice together.
  • Use the 60-30-10 balance to keep an accent color effective without letting it take over the screen.
  • Recognize the dark-mode contrast traps that light-mode testing never catches.

Color gets treated like a taste question: pick something that "feels right" and move on. WCAG turned it into a measurement instead. The moment you pick two colors, they have a specific, calculable contrast ratio, and that ratio either clears a defined line or it does not. This guide covers what a contrast ratio actually is, the exact WCAG 2.2 minimums for text, UI parts, and color-only meaning, worked pass and fail examples with real hex values, how to build a palette by role instead of by hue, the common dark-mode traps, and an honest look at what might eventually replace this math.

What a contrast ratio actually measures

A contrast ratio is not a measure of how different two colors look to you. It is a ratio of relative luminance: a formula-derived number for how much light a color effectively reflects, weighted for how the human eye responds differently to red, green, and blue. Every color converts to a luminance value between 0 (black) and 1 (white). The WCAG formula is (L1 + 0.05) / (L2 + 0.05), where L1 is the lighter color's luminance and L2 is the darker one's.

The result always lands between 1:1 and 21:1. Two colors with the same luminance sit near 1:1 no matter how different their hues look on paper: a saturated blue and a saturated red can land at almost the same luminance and read as nearly no contrast at all once brightness is the only thing separating them, which is close to what some forms of color vision deficiency actually experience. Pure black text on pure white is the maximum, 21:1. Every design choice you make lives somewhere on that scale, and the WCAG success criteria draw specific lines across it.

New to this? You do not need to run this formula by hand. A contrast checker, like the free one from WebAIM, takes two hex codes and returns the ratio in one step.1 What matters is knowing which ratio you need for the job in front of you, which the next section covers.

The WCAG 2.2 minimums

1.4.3 Contrast (Minimum) covers text. At Level AA it requires "a contrast ratio of at least 4.5:1" for normal text and at least 3:1 for large text.2 "Large" has an exact definition, not a feeling: 18 point (about 24px) or larger, or 14 point (about 18.7px) bold or larger.2 Below that size, text needs the stricter 4.5:1, because thin strokes at small sizes get harder to read at low contrast faster than thick ones do.

1.4.11 Non-text Contrast extends the same idea to things that are not text: user interface components, such as button borders, input outlines, and toggle states, and graphical objects, such as icon strokes and chart segments needed to understand the content, need at least 3:1 against whatever sits next to them.3 The reading is strict: the criterion's guidance notes that "computed values should not be rounded," so a 2.99:1 pair fails, full stop.3

What it applies toAA minimumAAA minimumCriterion
Normal text (under ~24px, or under ~19px bold)4.5:17:11.4.3 (AA), 1.4.6 (AAA)
Large text (headings usually qualify)3:14.5:11.4.3 (AA), 1.4.6 (AAA)
UI components (borders, inputs, toggles, focus rings)3:1No AAA level1.4.11
Graphical objects (icons, chart parts needed to understand content)3:1No AAA level1.4.11
Meaning conveyed by color aloneNot allowed, at any ratioNot allowed, at any ratio1.4.1
The WCAG 2.2 contrast minimums, by what you are styling

Decorative text, inactive controls, and logos sit outside 1.4.3 and 1.4.11 by definition. That exemption is easy to lean on too hard, so treat it narrowly: if a "disabled" button is still legible enough that people try to click it, the interface needs more than a lower contrast ratio to say "not now," such as a lock icon or a visible reason in a tooltip.

Two pairs, worked out

Numbers are easier to trust once you see them applied to real hex values instead of abstract percentages. Here are four pairs, each computed with the standard WCAG relative-luminance formula above.

PairRatioVerdict
White text #FFFFFF on navy #1E3A5F11.5:1PASS, clears AAA for text too
Gray text #9CA3AF on white #FFFFFF2.54:1FAIL, misses even the 3:1 large-text floor
Gray #8A8A8A used as a button border on white3.45:1PASS as a border or icon (1.4.11); the same gray used as body text FAILS (needs 4.5:1)
Blue link #3B82F6 on white, set at large-text size (24px)3.68:1PASS at large text size; FAILS at normal 16px body size
Pass, fail, and it depends

The first two rows are a clean pass and a clean fail. The last two are the ones people actually get wrong in practice: a ratio is not "good" or "bad" on its own, it is good or bad relative to the job the color is doing. #8A8A8A at 3.45:1 makes a perfectly fine input border. Set that exact gray as paragraph text and it fails, because text carries a stricter 4.5:1 bar than a border does. The blue link is fine as a large heading and fails as a small inline link, for the same reason: size changes which threshold applies, not whether the hex code itself is "accessible."

Key idea
A hex value does not pass or fail by itself. It passes or fails for a specific job, body text, large text, a UI control, or a decorative graphic, against a specific background. Check the pair against the job, not just against each other.

Never rely on color alone

1.4.1 Use of Color is a separate rule from the ratio criteria, and it trips up designs that pass every contrast check and still fail. It requires that "color is not used as the only visual means of conveying information, indicating an action, prompting a response, or distinguishing a visual element."4 A form field outlined in red for "error," with no icon, no message, and no other change, fails this even if that red clears 3:1 against the background.

This matters because color vision deficiency is common, not rare. About 1 in 12 men have some form of color vision deficiency, most often trouble telling red from green, according to the National Eye Institute.5 Add grayscale or low-quality displays, glare, and ordinary situational cases like bad lighting or aging eyes, and "just make it red" stops being a reliable signal for a meaningful share of any real audience.

The fix is cheap: pair the color with a second, non-color cue. An error state gets a red border, an icon, and a text message, not just a red border. A required field gets an asterisk or the word "required," not only a tinted background. A chart gets patterns or direct labels in addition to a color legend. None of this asks you to give up color. It asks you not to make color carry the entire message by itself.

Build the palette by role, not by hue

The fastest way to end up with a palette that fails half its own contrast checks is to pick colors because they look good together, then try to fix accessibility after the fact. Build it in the other order: decide the role each color plays first, then choose the hue that satisfies that role's requirement.

  • Background: the base surface color. Usually the least saturated choice on the page; every other color is measured against it.
  • Text: body copy, headings, labels. Must clear 4.5:1 (or 3:1 at large sizes) against every background it actually sits on, not just the main one.
  • Accent: buttons, links, active states, the one or two colors that mean "interact here." Needs 3:1 against the background where it functions as a UI component, and the full 4.5:1 where it also doubles as text.

A simple discipline keeps this from sprawling into a dozen shades: the 60-30-10 balance, borrowed from interior design and applied to interfaces. Roughly 60% of the screen is the dominant background and surface color, 30% is a secondary color (cards, panels, secondary text), and 10% is the accent, reserved for the handful of things that should draw the eye first, like a primary button or an active state. Because the accent covers a small minority of the screen, it can afford to be your boldest, least background-like color without dominating the page or turning into noise.

  1. 1Name the roleIs this text, a UI control (border, icon, focus ring), or a decorative graphic?
  2. 2Pick the thresholdText needs 4.5:1 (3:1 if large). Controls and graphical objects need 3:1.
  3. 3Measure the real pairCheck contrast against the actual background it renders on, not the page's average color.
  4. 4Test color-only meaningIf color is the only signal, add an icon, a label, or a pattern too.
  5. 5Recheck every stateHover, focus, disabled, and dark mode each have their own ratio. Test them separately.
Before you ship a color pair

Dark-mode contrast pitfalls

Dark mode looks like a simple swap: invert the palette and ship it. In practice it breaks contrast in ways a light-mode design never surfaces.

  • Pure white on pure black overshoots. #FFFFFF on #000000 measures 21:1, the maximum possible ratio, and large blocks of it at that extreme can cause halation and eye strain for some readers. Many dark-mode systems deliberately dial the "white" down to an off-white and the "black" up to a near-black, which still clears every AA and AAA threshold with plenty of room to spare.
  • Translucent text quietly fails. A common pattern is a white foreground at partial opacity for secondary text. The rendered color depends on whatever sits underneath it, so the same CSS value can pass on one background and fail on a slightly different one right next to it. Measure the flattened, on-screen result, not the opacity value in isolation.
  • One accent rarely survives both themes. A saturated accent that clears 4.5:1 on white often falls short on a dark surface, or the reverse. Treat light and dark as two separate palettes carrying the same roles, not one palette with an automatic filter applied on top.
  • Borders and dividers go invisible first. A line that was barely legal on a light background often drops under 3:1 once the surrounding luminance flips, and nobody notices until someone reports it.
Going further: WCAG 2.2's contrast math treats all midtones the same way, which is not quite how human perception works; a gray that measures "5:1" against black can look noticeably lower-contrast than the same 5:1 against white. APCA (the Accessible Perceptual Contrast Algorithm) is a newer model built to correct for that, and it is the contrast method being developed for WCAG 3.0.6 Neither one is finished. WCAG 3.0 is still a W3C Working Draft, explicitly marked as a document that "may be updated, replaced, or obsoleted by other documents at any time."7 APCA itself is documented by its own project as a beta library and a draft "Readability Criterion" still described as "a work in progress," built under a collaboration with the W3C group but not yet an adopted standard.6 Build against WCAG 2.2's 4.5:1 and 3:1 ratios today. They are what tools, audits, and legal standards check against right now. Treat APCA as worth watching, not worth switching to yet.
Key idea
Three numbers cover almost every case: 4.5:1 for normal text, 3:1 for large text and for UI components and graphics, and one rule that has no ratio at all, never let color alone carry the meaning.
Read next: The core laws of UX and UI design covers the perception and memory research behind layout, grouping, and attention. Pair it with Shipping web apps for where color and contrast decisions actually land in a real build.

Sources

Verified against primary sources: August 2026.

  1. WebAIM Contrast Checker. WebAIM. https://webaim.org/resources/contrastchecker/
  2. Understanding Success Criterion 1.4.3: Contrast (Minimum). W3C Web Accessibility Initiative (WAI), WCAG 2.2. https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html
  3. Understanding Success Criterion 1.4.11: Non-text Contrast. W3C Web Accessibility Initiative (WAI), WCAG 2.2. https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html
  4. Understanding Success Criterion 1.4.1: Use of Color. W3C Web Accessibility Initiative (WAI), WCAG 2.2. https://www.w3.org/WAI/WCAG22/Understanding/use-of-color.html
  5. Color Blindness. National Eye Institute, U.S. National Institutes of Health. https://www.nei.nih.gov/learn-about-eye-health/eye-conditions-and-diseases/color-blindness
  6. APCA (Accessible Perceptual Contrast Algorithm), apca-w3. Andrew Somers / Myndex Research. https://github.com/Myndex/apca-w3
  7. WCAG 3.0 (Working Draft). W3C. https://www.w3.org/TR/wcag-3.0/
Read nextThe core laws of UX and UI design