GenShelf
All guides

Color contrast that passes: a practical WCAG checklist for UI

12 min read · Written by the GenShelf editor · Updated August 2026

A palette can look harmonious in a swatch row and still fail in a real interface. Contrast is the difference in perceived lightness between text (or UI) and its background. WCAG contrast rules are a practical floor for readability — not a style straitjacket. This guide translates the common ratios into decisions you can make while designing, and shows how to fix pretty-but-unreadable combinations without throwing out your brand.

The numbers that matter day to day

  • Normal text: aim for at least 4.5:1 against its background (WCAG AA). Body copy, form labels, and navigation links count here.
  • Large text: roughly 3:1 can pass AA when type is large and bold enough (commonly 18pt+ regular or 14pt+ bold — check the current WCAG definitions for your context).
  • Non-text UI: icons, input borders, and focus rings that convey meaning generally need about 3:1 against adjacent colors.
  • AAA: stricter ratios (7:1 for normal text) help dense reading experiences; treat them as a goal for long-form content, not a blocker for every badge.

Decorative flourishes that convey no information are exempt in spirit — but if users need the color to understand state (error, selected, disabled), measure it.

Where palettes usually fail

Soft gray text on white feels “modern” and often sits around 2–3:1 — fine for captions you do not care about, bad for anything people must read. Mid- saturation brand colors on mid-gray backgrounds fail in both light and dark themes. Placeholder text that matches disabled text confuses state. Charts that rely on red vs green alone fail for many users even when contrast ratios look acceptable pairwise.

Dark mode is not “invert everything.” Light text on a dark surface still needs measurable contrast, and thin light type on pure black can bloom on some screens. Design both themes with the same checklist, not as an afterthought toggle.

A fix workflow that preserves brand

  1. Lock the roles: background, body text, muted text, primary accent, borders, danger.
  2. Measure body text vs background first. If it fails, darken (or lighten) the text before you abandon the brand hue.
  3. Keep the accent for buttons and links, but ensure button label contrast on the accent fill passes — not only the accent on the page background.
  4. Reserve true muted grays for secondary content; do not use them for primary instructions.
  5. Recheck hover, focus, and error states. Focus rings need to be visible on both light and dark surfaces.

A free color palette generator with contrast checks helps you catch failures while you still have locked swatches to adjust — before the palette ships into components.

Text on images and gradients

Hero photos and gradient washes break flat contrast math because the background is not one color. Solutions that work: a solid scrim behind type, text in a panel, or positioning copy over a consistently dark (or light) region of the image. Do not rely on a drop shadow alone for body copy. If marketing insists on type over a busy photo, treat it as large display text and still verify the worst patches of the image.

Components to audit every time

  • Body and heading text on default backgrounds
  • Links and buttons (default, hover, disabled)
  • Form borders, labels, helper text, and errors
  • Table headers and zebra rows
  • Toast and banner text on status colors
  • Chart labels and legend keys (add patterns or labels, not color alone)

Build a tiny contrast checklist into design QA the same way you check spelling. One failed primary button label undoes a polished palette. Prefer fixing tokens centrally so every screen inherits the correction instead of one-off hex edits in random components.

Brand color without sacrificing ratio

Keep the vivid brand hue for accents and large fills; derive a darker (or lighter) sibling for small text that must sit on white or near-black. Many design systems ship “brand,” “brand-hover,” and “on-brand” text tokens for exactly this reason. If marketing insists that body copy use the bright brand color on white, show the failed ratio and offer a nearby shade that still reads as the brand family.

Gradients on buttons need the label checked against the lightest and darkest stops the text crosses. If either fails, flatten the fill under the label or choose a neutral label color that passes on both.

Disabled and muted states

Disabled controls are allowed to look quieter, but helper text that explains an error is not “muted decoration.” Keep error and instructional copy at readable contrast even when the adjacent input is disabled. Placeholder text inside fields should not be your only label — when the user types, the placeholder disappears, and low-contrast placeholders fail many readers before that.

Contrast is not the whole accessibility story

Passing AA does not fix tiny tap targets, missing focus order, or color as the only error signal. Use contrast as a gate, then keep going. For building the palette itself — analogous sets, roles, and workflow — see color palette basics. Readable UI is a contrast habit: measure the pairs people actually read, fix the failures in the tokens, and stop shipping soft gray as a personality trait.

Try it on GenShelf: Free Color Palette Generator

Related guides