# How to check color contrast in a UI

Color contrast compares the relative luminance of a foreground and its background. Measure the actual pair, apply the criterion that fits the content, and inspect every relevant state. A passing pair is one accessibility check; it does not certify an entire component or page.

By The Design Project. Updated 2026-10-21.

## What you will make

A contrast review table covering the text and controls in one interface.

## Before you start

- The actual foreground and background colors
- The text size and weight
- A list of interaction states and supported themes

## Contrast is a relationship, not a property of one color
A contrast check compares a foreground with the background behind it. The same gray can be readable on one surface and insufficient on another. The task is to identify the actual pair, select the applicable requirement, and verify the component in the state people will use.

This guide focuses on an inspectable review workflow. Use the calculator as a starting point, then examine the real interface. Text over images, translucent layers, gradients, and changing backgrounds needs more than a single palette swatch.

Keep the review bounded to a screen or flow so you can record the result and fix the relevant source tokens. Passing contrast checks is one part of accessibility, not certification of the whole page.

## Step 1. Identify the actual pair
Inspect the rendered text and the surface immediately behind it. Account for transparency, overlays, images, and gradients: a solid-color calculator cannot represent all of those conditions. The tool on this page accepts opaque six-digit sRGB hex colors. For more complex backgrounds, inspect the least favorable area behind the content with an appropriate tool.

## Step 2. Choose the relevant criterion
WCAG 2.2 distinguishes ordinary text, large text, and certain non-text visual information. Large text means at least 18pt, or 14pt bold, approximately 24 CSS px and 18.67 CSS px respectively. Use the original criteria for exact scope and exceptions.

| Content | AA contrast reference | What to examine |
| --- | --- | --- |
| Ordinary text | At least 4.5:1 | Text against its background |
| Large text | At least 3:1 | Confirm the size and weight qualify |
| Necessary UI/state graphics | At least 3:1 | Relevant adjacent colors; exceptions apply |

The calculator’s UI reference is only a numeric check. It cannot decide whether a particular border is necessary to identify a control or whether an exception applies.

## Step 3. Measure and record
Enter the pair into the checker. Record the original values, the unrounded result used for the decision, the content type, and the state. Do not round a value below the threshold upward to claim a pass. Keep screenshots for context, but preserve the actual values so another reviewer can reproduce the check.

## Step 4. Adjust the role, not just the swatch
If a pair fails, consider changing text color, surface color, or the functional variant of an accent. Recheck the surrounding hierarchy and all uses of the token. Darkening a shared color for one button can affect links or status messages elsewhere. Avoid solving a contrast problem by increasing weight without checking whether the text still qualifies under the intended criterion.

## Step 5. Review states and additional cues
Inspect default, hover, focus, selected, error, and supported themes. Read the message without relying on hue. Keyboard focus, labels, semantics, and error recovery need their own checks even when a color pair passes. Keep unresolved cases visible in the review report.

## Worked example: review a settings form
Start with the form’s visible text: heading, labels, entered values, hints, errors, and button labels. Record each actual foreground and surface. Then inspect the visual information needed to recognize controls and states, such as a field boundary or selected indicator.

For ordinary text, WCAG 2.2 AA uses a minimum contrast ratio of 4.5:1; qualifying large text uses 3:1. Large text is at least 18 point, or 14 point bold. The [W3C explanation of text contrast](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum) also describes exceptions and why thresholds must not be rounded up.

Do not classify a small label as large text just because it is bold. Record size and weight with the pair so another reviewer can apply the same criterion.

| Element | Pair to inspect | Additional question |
| --- | --- | --- |
| Field label | Label color against form surface | Is the label associated with its control? |
| Hint | Hint color against its actual surface | Is essential information too faint? |
| Error | Error text against feedback surface | Is the error also explained in words? |
| Button | Label against each supported fill state | Does focus remain visible? |
| Selected control | State indicator against adjacent colors | Can the state be identified without hue alone? |

## Fix the role rather than one screenshot
If secondary text fails on several cards, inspect the shared semantic token and intended surfaces. A local override may fix the screenshot while leaving the same problem elsewhere. Conversely, changing a global primitive can affect roles that were already correct. Choose the level that expresses the actual problem.

Try a darker foreground, lighter surface, or a different approved pairing, then recheck the full component. Increasing saturation alone does not reliably improve contrast. Keep the visual hierarchy intact while meeting the relevant requirement.

## Check transparency and changing backgrounds
An opacity value can make a color blend with what is behind it. Record both the source value and the rendered context. A label over a photograph may encounter multiple backgrounds across responsive crops, so one sampled point is not enough evidence for the whole treatment.

Consider a stable surface behind important text when the background is unpredictable. Recheck the actual implementation rather than assuming a shadow or overlay has solved every possible combination.

## Include interaction states in the evidence
A default button can pass while hover or focus treatment fails. A field can become unreadable in an error state. Review supported states and themes explicitly, and record the ones you could not exercise.

Unavailable controls have specific exceptions under some contrast criteria, but an exception is not a reason to make surrounding explanations hard to read. Users still need to understand why an action is unavailable and what they can do next.

## Write a useful finding
A useful report names the element, viewport or theme, foreground, background, measured ratio, applicable criterion, and suggested fix. Add a source path or screenshot so the issue can be reproduced. After the fix, record the new result and check nearby consumers of the changed token.

Use [semantic color tokens](https://designproject.io/resources/guides/create-semantic-color-tokens/) to keep approved pairings consistent. For the rest of the flow, continue with the [accessibility skill resource](https://designproject.io/resources/skills/accessibility/) and review keyboard operation, labels, focus, and error communication as well.

## Completion checklist
- The measured pair matches the rendered interface.
- The correct content category is used.
- Threshold decisions use the full result, not a rounded display.
- Changes were checked across token consumers.
- The report separates contrast results from broader accessibility findings.

## Common questions
### Can this checker certify WCAG compliance?
No. It calculates a solid-color contrast ratio and compares numeric thresholds. Accessibility conformance involves more criteria and context.
### Are disabled controls subject to the same contrast rules?
The contrast criteria include exceptions for inactive components. Evaluate whether the control is truly inactive and keep the surrounding explanation usable.

## Sources
- [W3C: Contrast (Minimum)](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html)
- [W3C: Non-text Contrast](https://www.w3.org/WAI/WCAG22/Understanding/non-text-contrast.html)


## Related guides

- [How to create a UI color palette, step by step](https://designproject.io/resources/guides/create-ui-color-palette/)

- [How to create semantic color tokens for UI](https://designproject.io/resources/guides/create-semantic-color-tokens/)

- [Font weight, border width, and icon strokes: a UI guide](https://designproject.io/resources/guides/font-weight-borders-strokes/)

[Product design glossary](https://designproject.io/resources/glossary/)

Canonical: https://designproject.io/resources/guides/check-color-contrast/

## Keep learning

- [How to create a UI color palette, step by step](https://designproject.io/resources/guides/create-ui-color-palette/)
- [Product design glossary: 44 terms explained](https://designproject.io/resources/glossary/)
- [How to create semantic color tokens for UI](https://designproject.io/resources/guides/create-semantic-color-tokens/)
