Skip to content
motifuse
Guide
17 min read

WCAG Color Contrast: Ratios, Rules and Testing

Learn the WCAG color contrast ratios for text, controls, icons and focus states, then follow a practical workflow to test light and dark themes.

The motifuse team

Color contrast problems rarely announce themselves. A page can look polished on a bright designer monitor and still make body text, form borders, or keyboard focus nearly disappear for someone with low vision, color-vision deficiency, an aging display, or glare on a phone.

The good news is that contrast is measurable. The Web Content Accessibility Guidelines (WCAG) define specific ratios for text and meaningful interface elements, so teams do not have to judge accessibility by eye. The harder part is knowing which ratio applies, which two colors to test, and what to do when a brand color fails.

This guide explains the WCAG 2.2 contrast rules in practical terms, then turns them into a repeatable audit and repair workflow for websites and web applications.

What color contrast actually measures

Color contrast describes the difference in relative luminance between a foreground and its background. Relative luminance is a calculated measure of how light a displayed color appears, not simply how different two hue names sound.

That distinction matters. Red and green may look like very different colors to one person while having similar luminance and weak contrast. Conversely, two shades from the same blue family can have strong contrast if one is much lighter than the other.

WCAG expresses contrast as a ratio from 1:1 to 21:1:

  • 1:1 means the two colors have the same relative luminance.
  • 21:1 is the maximum contrast, produced by black and white.
  • A larger first number means a stronger light-dark difference.

The WCAG formula compares the lighter relative luminance (L1) with the darker one (L2):

Using the WCAG formula, contrast ratio = (L1 + 0.05) / (L2 + 0.05).

You usually do not need to calculate this manually. A contrast checker converts the color values, applies the luminance formula, and reports the ratio and relevant pass or fail results.

The WCAG contrast ratios at a glance

WCAG has different requirements for body text, large text, enhanced conformance, and meaningful non-text visuals. The following table covers the decisions most teams make during an audit.

Content being testedWCAG levelMinimum ratioTest against
Normal text and images of textAA4.5:1The text background
Large textAA3:1The text background
Normal text and images of textAAA7:1The text background
Large textAAA4.5:1The text background
Required control boundaries, states, and meaningful graphicsAA3:1Adjacent color or colors

For most public websites, WCAG Level AA is the practical target. Level AAA can improve readability further, but it is stricter and is not intended as a blanket requirement for every type of content.

What counts as large text?

Under WCAG, large-scale text is at least 18 points when it is regular weight, or at least 14 points when it is bold. In CSS terms, those values are approximately 24px and 18.5px because 1pt equals about 1.333px.

Do not classify a heading as large merely because it feels prominent. Its rendered size and weight must meet the definition. Thin or unusual typefaces can also appear fainter than their declared color suggests, so passing the mathematical minimum is not always a good visual target.

What counts as non-text contrast?

WCAG 2.2 Success Criterion 1.4.11 requires at least 3:1 contrast for visual information needed to identify an active interface component or its state. It also applies to parts of a graphic required to understand its meaning.

Common examples include:

  • The visible border that identifies a text input
  • A check mark that communicates a selected checkbox
  • The track or thumb needed to understand a toggle
  • An icon used without a visible text label
  • A data line against a chart background
  • A custom focus indicator against adjacent colors

The rule is about necessary visual information, not every decorative edge. A button may be identifiable through its label, position, and context without needing a 3:1 outline. If a subtle border is the only cue that an empty area is an input, however, that border is necessary and must be tested.

Which elements are exempt?

WCAG 1.4.3 excludes incidental text, pure decoration, invisible content, and text in inactive interface components. Text that forms part of a logo or brand name is also exempt from the text-contrast requirement.

Non-text contrast similarly excludes inactive controls, visuals whose appearance is set by the browser and not modified by the author, and graphics whose exact presentation is essential to the information, such as a faithful screenshot.

These are narrow conformance exceptions, not reasons to make content difficult to perceive. Disabled text still needs to communicate why an action is unavailable in many real interfaces. A low-contrast logo used as the only home link may also be hard to find even if the logotype itself is exempt. Treat the exceptions as legal boundaries of the criterion, not design goals.

A practical workflow for testing color contrast

A reliable audit tests rendered components in context. A palette spreadsheet alone cannot show how transparency, state changes, gradients, or theme overrides affect the final pixels.

1. Inventory every theme and component state

Start with the screens people actually use. Include light and dark themes, responsive layouts, modal surfaces, banners, data visualizations, and third-party widgets that inherit your styles.

For interactive components, inspect more than the default state:

  1. Default
  2. Hover
  3. Keyboard focus
  4. Active or pressed
  5. Selected or checked
  6. Error, warning, and success
  7. Disabled, even when it is technically exempt

A button can pass at rest and fail on hover when its background becomes lighter. A focus ring that looks clear on the page background may disappear where the same button sits inside a dark card.

2. Identify the real foreground and adjacent background

Use the computed CSS color, not a value copied from a design file. For text, test the text color against the color immediately behind it. For a border, icon, or focus ring, test it against every color it touches when those adjacent colors affect perception.

If opacity is involved, test the composited result. For example, rgba(0, 0, 0, 0.5) does not have one fixed contrast ratio; its final color depends on the surface underneath it.

3. Classify the content before choosing a threshold

Ask three questions:

  • Is this normal text, large text, or necessary non-text information?
  • Are you testing Level AA or the enhanced Level AAA criterion?
  • Is the element active and meaningful, or is it decorative or inactive?

This classification prevents two common errors: applying the relaxed 3:1 large-text rule to ordinary text, and demanding 4.5:1 from every decorative border even though meaningful non-text visuals generally use 3:1.

4. Test the exact pair

Enter the foreground and background values into a reliable checker. The Color Contrast Checker reports the numerical ratio and shows the AA and AAA outcomes for normal and large text.

Try it right here

Color Contrast Checker

Open full tool
Loading embedded tool...

Keep the ratio with the component record in your audit. A bare pass or fail is less useful because it does not show how close the design is to the threshold.

5. Fix the system, not one isolated screen

When a color fails, find the design token or component variant that produced it. Changing text-muted once can repair captions, secondary labels, timestamps, and placeholders across the product. A one-off hex override may only hide the same defect elsewhere.

Usually the least disruptive fix is to adjust lightness while keeping the general hue. Other options include:

  • Darken foreground text on a light surface.
  • Lighten foreground text on a dark surface.
  • Use a darker button fill behind white text.
  • Add a solid surface or scrim behind text placed over an image.
  • Strengthen borders that are required to identify form controls.
  • Add labels, icons, patterns, or underlines when color carries meaning.

6. Retest in context

After updating the token or component, repeat the audit in every theme and state. Then check at browser zoom, with a keyboard, on a narrow viewport, and in an operating-system high-contrast or forced-colors mode if the product supports it.

Automated tests are valuable for catching known color pairs, but they cannot always determine which background is visually adjacent or whether a graphic is essential. Use automation as a regression guard alongside manual review.

Worked color-pair examples

The following examples use the WCAG relative-luminance calculation. They show why guessing from a color name is unreliable.

ForegroundBackgroundRatioResult for normal text at AA
#1F2937#FFFFFF14.68:1Pass
#6B7280#FFFFFF4.83:1Pass
#9CA3AF#FFFFFF2.54:1Fail
#FFFFFF#2563EB5.17:1Pass
#FFFFFF#3B82F63.68:1Fail for normal text; pass for large text

The two blue buttons may look like small variations of the same brand color, yet white normal-size text passes on one and fails on the other. This is why a brand palette needs role-specific tokens such as action-background and action-text, not a rule that every shade is interchangeable.

Fixing common interface patterns

Body text, muted text, and placeholders

Body copy needs at least 4.5:1 at Level AA. Secondary text does not get a lower threshold just because it is called “muted.” Captions, timestamps, helper text, and placeholders are still text when they communicate information.

Avoid designing placeholder text as a substitute for a persistent label. Even with sufficient contrast, placeholder content disappears as soon as someone types, making the field harder to review and correct.

Readable content also depends on sentence structure and vocabulary, not just color. After the visual audit, a readability check can identify dense sentences and difficult passages that a contrast ratio cannot detect.

Every link must meet the text-contrast requirement against its background. If color is the only cue separating a link from surrounding text, WCAG's documented technique uses at least 3:1 contrast between link and body text plus an additional visual cue on hover or focus.

The simpler and more robust pattern is to underline inline links. The underline survives grayscale viewing, reduces dependence on hue perception, and removes the need to make links dramatically different from surrounding copy.

Forms, errors, and status messages

Do not identify a failed field only with a red border. Add an error icon or text message, associate the message programmatically with the control, and preserve a visible focus indicator. The text, icon, input boundary, and state indicator each need to be evaluated against the surface they touch.

The same principle applies to success and warning states. “Green means complete” is not sufficient by itself. Pair color with words, symbols, or patterns so the meaning survives when colors are not distinguishable.

Buttons and focus indicators

Test a button label against the button fill, then test any required boundary against the surrounding surface. Test the focus indicator separately wherever the component can appear.

A clear two-color focus treatment is useful when one outline color cannot work across mixed backgrounds:

css
:root {
  --action-bg: #2563eb;
  --action-text: #ffffff;
  --focus-inner: #ffffff;
  --focus-outer: #0f172a;
}

.button {
  background: var(--action-bg);
  color: var(--action-text);
}

.button:focus-visible {
  outline: 2px solid var(--focus-inner);
  box-shadow: 0 0 0 4px var(--focus-outer);
}

Do not remove the browser outline unless an equally visible replacement is ready. WCAG 2.2 also includes an enhanced Level AAA Focus Appearance criterion; its simplest conforming pattern is a solid indicator at least two CSS pixels thick with a 3:1 change of contrast between focused and unfocused states.

Icons, SVGs, and charts

An icon that is the only visible label for an action needs 3:1 contrast against its background. Decorative icons do not need the same treatment, but lowering their contrast should not make the interface harder to scan.

For SVG interface icons, using currentColor can keep the icon aligned with a tested text token instead of embedding an ungoverned fill value. Once an SVG is accessible and correct, the SVG Optimizer can reduce unnecessary markup without changing its intended appearance.

Charts need more than a high-contrast palette. Add labels, shapes, line styles, or patterns so color is not the only way to distinguish series. When a visual can be understood from visible labels and values, users do not have to infer meaning from neighboring colors alone.

Contrast in dark mode

Dark mode is a separate color system, not a mechanical inversion. A text color that passes on white says nothing about its performance on a charcoal surface. Shadows may disappear, saturated colors can appear to vibrate, and a light focus ring can vanish against a light card embedded in an otherwise dark page.

Audit each dark-theme pair independently. Keep semantic roles stable while allowing their color values to change:

css
:root {
  --surface: #f8fafc;
  --text: #0f172a;
  --text-muted: #475569;
}

[data-theme="dark"] {
  --surface: #0f172a;
  --text: #f8fafc;
  --text-muted: #94a3b8;
}

In this example, the light-theme main pair is about 17.06:1, the light-theme muted pair is about 7.24:1, and the dark-theme muted pair is about 6.96:1. The values are intentionally different because each token is tuned for its own surface.

Difficult cases: images, gradients, and transparency

Text over a photograph may pass in one area and fail a few pixels away. Gradients have the same problem. Test the least-contrasting area the text can occupy, including responsive crops and animation frames.

Reliable fixes include:

  • Place text on a solid panel.
  • Add a sufficiently opaque scrim between image and text.
  • Constrain the crop so the text always sits over a predictable region.
  • Add a strong text backing treatment rather than relying on a soft shadow.

Keep real text as HTML when possible. Text baked into an image is harder to resize, translate, restyle, and adapt to high-contrast preferences. If a content image is necessary, optimize it without destroying legibility; the guide to compressing images for the web explains how to balance file size and visible quality.

For semi-transparent foregrounds, calculate or sample the final composited color on every supported surface. The same 50% black overlay produces different results on white, blue, and photographic backgrounds.

Do not rely on color alone

Contrast and color-independent meaning are related but separate requirements. A red error label can have excellent contrast and still fail users if red is the only indication that something is wrong.

Use at least one additional cue:

  • Text such as “Error” or “Required”
  • A persistent underline for links
  • An icon paired with a visible label
  • Patterns or line styles in charts
  • Shapes as well as colors in status badges
  • Position and explicit labels in legends

This does not mean removing color. Color is useful for recognition and emphasis. The goal is to ensure that information remains understandable when hue differences are unavailable.

Common contrast-audit mistakes

  • Testing palette swatches instead of components. A color does not pass by itself; it passes or fails against a specific adjacent color in a specific role.
  • Forgetting responsive and theme variants. Mobile navigation, dark mode, dialogs, and hover or selected states often introduce untested pairs.
  • Rounding a near miss upward. Threshold values are strict. 2.999:1 is not 3:1, and 4.499:1 is not 4.5:1.
  • Treating all large-looking text as large text. Verify the rendered size and weight against the WCAG definition.
  • Ignoring opacity and overlays. The declared RGBA value is not the final displayed color.
  • Assuming contrast makes color-only meaning accessible. A passing red border still needs another error cue.
  • Sampling anti-aliased glyph edges. Test underlying computed colors; edge pixels are blended by rendering.
  • Stopping at automated scans. Tools cannot always understand adjacency, meaning, or every transient state.

A maintainable contrast checklist

Use this short list when designing a component, reviewing a pull request, or preparing a release:

  1. Test normal text at 4.5:1 or higher for Level AA.
  2. Use the 3:1 large-text threshold only when size and weight qualify.
  3. Test required control cues and meaningful graphics at 3:1 against adjacent colors.
  4. Check default, hover, focus, active, selected, error, and disabled states.
  5. Audit light and dark themes independently.
  6. Test composited colors when opacity, images, or gradients are involved.
  7. Add a non-color cue wherever color communicates meaning.
  8. Record ratios with semantic design tokens and component documentation.
  9. Recheck keyboard focus and forced-colors behavior manually.
  10. Add regression checks for stable color pairs without relying on automation alone.

Contrast is easiest to maintain when it is part of the design system. Define approved foreground-background pairs, name tokens by purpose, document which surfaces they support, and test components whenever a token changes. That turns accessibility from a late visual cleanup into an ordinary engineering constraint.

Frequently asked questions

What is the minimum WCAG contrast ratio for body text?
At WCAG Level AA, normal text and images of text need at least 4.5:1 contrast against their background. Large-scale text needs at least 3:1. The Level AAA enhanced thresholds are 7:1 for normal text and 4.5:1 for large text.
Does all interface text need a 4.5:1 contrast ratio?
Most visible text that communicates information does at Level AA, including helper text, placeholders, and text shown on hover or focus. Narrow exceptions include inactive controls, pure decoration, incidental text, invisible content, and logotypes.
Do icons and form borders need 4.5:1 contrast?
Not generally. Required visual information that identifies active controls, states, or meaningful graphics uses a minimum of 3:1 against adjacent colors under WCAG 1.4.11. Decorative shapes do not automatically need that ratio.
Can a brand color fail WCAG?
A color does not pass or fail in isolation. A specific foreground-background pair passes or fails for a particular role. Keep the brand hue where possible, but create lighter or darker accessible variants for text, button fills, links, borders, and focus indicators.
Is dark mode automatically more accessible?
No. Dark mode can reduce glare for some people, but it introduces its own foreground-background pairs and component states. Test it independently rather than assuming an inverted palette will preserve contrast.
Is passing a contrast checker enough for accessibility?
No. A checker verifies a color pair and threshold. It cannot guarantee readable typography, visible focus, correct labels, color-independent meaning, useful alt text, keyboard operation, or understandable content. Contrast testing is one part of a broader accessibility review.

Conclusion

WCAG contrast testing becomes manageable once every decision is reduced to three facts: what the element communicates, which colors are actually adjacent, and which threshold applies. Normal text usually needs 4.5:1, large text and necessary non-text cues usually need 3:1, and enhanced AAA text targets are higher.

Test real components rather than isolated swatches, include every state and theme, and fix shared tokens so improvements propagate through the product. Most importantly, remember that contrast cannot replace meaning: labels, underlines, patterns, and visible focus cues keep an interface understandable even when color perception changes.

Sources and image credit

The technical requirements in this guide are based on the W3C's Web Content Accessibility Guidelines 2.2, Understanding Contrast (Minimum), Understanding Non-text Contrast, and Understanding Use of Color. For operating-system contrast preferences, see the MDN prefers-contrast reference and MDN forced-colors reference.

Cover photo: “Hands Selecting Color Swatches at a Desk” by Mayara Caroline Mombelli, used under the Pexels licence. Alt text: Hands comparing printed color swatches at a design desk.

Put it into practice

Every guide comes with free tools to match.

Public tools open without sign-up. Local, upload, AI, and premium workspace steps are labeled clearly.

Explore all tools