WCAG Color Contrast Requirements Explained

WCAG 2 Level AA requires a contrast ratio of at least 4.5:1 for normal text, 3:1 for large text (18pt, or 14pt bold), and 3:1 for UI components and meaningful graphics. Level AAA raises text to 7:1 and 4.5:1 for large text.

The three success criteria that cover contrast

The Web Content Accessibility Guidelines (WCAG) handle color contrast in three places. The numbers are the same in WCAG 2.0, 2.1 and 2.2, except that 1.4.11 was added in 2.1.

CriterionLevelApplies toMinimum ratio
1.4.3 Contrast (Minimum)AANormal text4.5:1
1.4.3 Contrast (Minimum)AALarge text3:1
1.4.6 Contrast (Enhanced)AAANormal text7:1
1.4.6 Contrast (Enhanced)AAALarge text4.5:1
1.4.11 Non-text ContrastAAUI components and graphical objects3:1

Most organizations, and most accessibility laws and policies that reference WCAG, target Level AA. AAA is a stretch goal; W3C itself notes it isn't possible to meet every AAA criterion for all content.

How the contrast ratio is calculated

The ratio compares the relative luminance (perceived brightness) of two colors.

contrast = (L1 + 0.05) ÷ (L2 + 0.05)

L1 is the lighter color and L2 the darker. Luminance is calculated from the sRGB values after converting them to linear light, with green weighted most heavily (0.7152), then red (0.2126), then blue (0.0722). The result runs from 1:1 (identical colors) to 21:1 (black on white).

Two practical consequences: hue barely matters on its own, and you can't eyeball it. Yellow on white looks bright and colorful but has very poor contrast, while a dark blue may pass easily. Use the color contrast checker rather than guessing.

Worked example: gray text on white

Text colorRatio on #ffffffNormal text AALarge text AANormal text AAA
#9999992.85:1FailFailFail
#9494943.03:1FailPassFail
#7777774.48:1FailPassFail
#7676764.54:1PassPassFail
#5959597.00:1PassPassPass

Note that #777777 and #767676 look identical to most people, yet one fails and one passes. There's no rounding: 4.48:1 is below 4.5:1, so it fails.

What counts as large text

WCAG defines large text as at least 18 point, or at least 14 point bold. On the web, 1pt equals 1.333 CSS pixels, so:

  • 18pt regular ≈ 24px
  • 14pt bold ≈ 18.66px (often rounded to 18.7px; 18px bold does not quite qualify)

"Bold" means a font weight of 700 or heavier in practice. Thin or decorative typefaces can look smaller than their nominal size, so treat these thresholds as a floor, not a target. If your root font size is the default 16px, 24px is 1.5rem; see our CSS units guide for why rem is the better unit for type.

Non-text contrast (1.4.11)

Success Criterion 1.4.11 requires 3:1 against adjacent colors for:

  • Visual boundaries of controls when they're needed to identify the control, such as the border of a text input that has no background fill.
  • States such as focus rings, the check in a checkbox, or the selected state of a toggle.
  • Graphical objects needed to understand content, such as the lines in a chart or a meaningful icon without a text label.

A common failure is the light-gray input border, for example #e5e7eb on white, which is far below 3:1. If the field has a visible label and a contrasting background fill, the border itself may not be required, but the safest fix is a darker border. Buttons with a text label don't need their background to contrast with the page, because the text identifies the control; the text still needs 4.5:1 against the button.

Exemptions

The text criteria don't apply to:

  • Logotypes: text that is part of a logo or brand name.
  • Inactive components: text in disabled buttons and fields.
  • Incidental text: pure decoration, text that is not visible to anyone, or text inside a photo that has significant other visual content.

Some things people assume are exempt, but aren't: placeholder text in an active input, text over images or videos in a hero, error messages, and footer links. W3C's Understanding SC 1.4.3 document covers the edge cases in detail.

How to fix failing colors

1. Adjust lightness, not hue

The fastest fix is usually to darken the foreground (or lighten the background) while keeping the same hue. Convert the color with the HEX to RGB and HSL converter, lower the HSL lightness a few percent at a time, and re-check the ratio. A brand blue like #3b82f6 on white (3.68:1) only passes for large text; the darker #2563eb gives 5.17:1, which passes for all text at AA.

/* Before: fails as body text on white (2.85:1) */
.muted { color: #999999; }

/* After: passes AA (4.54:1) */
.muted { color: #767676; }

/* Link that must stand out from #333333 body text:
   add an underline so color isn't the only cue */
a { color: #1d4ed8; text-decoration: underline; }  /* 6.70:1 on white */

2. Keep a separate shade for text

Brand palettes often have a bright primary that works for big buttons and illustrations but not for small text. Define a darker "text" variant of each brand color and use it for links and labels.

3. Use size to your advantage

If a color must stay as it is, make the text large enough to qualify as large text, where 3:1 is enough at AA. That's a valid choice for headings, not for body copy.

4. Fix text over images

Check contrast against the lightest part of the image that sits behind the text. A semi-transparent dark overlay makes the result predictable:

.hero {
  background:
    linear-gradient(rgb(0 0 0 / 0.55), rgb(0 0 0 / 0.55)),
    url("hero.jpg") center / cover;
  color: #ffffff;
}

5. Don't rely on color alone

Contrast is related to, but separate from, SC 1.4.1 Use of Color. Links in body text that differ from surrounding text only by color need either a 3:1 difference from the body text plus another cue on hover and focus, or simply an underline. The underline is easier.

6. Test every state and theme

Check hover, focus, visited, error and dark mode colors, not only the default. A design that passes in light mode often fails in dark mode with muted grays.

What about APCA and WCAG 3?

The Accessible Perceptual Contrast Algorithm (APCA) is a newer method that accounts for font size, weight and polarity (dark text on light versus light on dark). It has been explored in WCAG 3 working drafts. WCAG 3 is still a draft, though, and its contrast method may change before it's finalized.

For now, APCA is not a conformance requirement. Audits, procurement checklists and the laws that reference WCAG use the WCAG 2.x ratios. You can use APCA as an extra design check, but meet the 2.x thresholds first.

Contrast checklist

  1. Body text and small labels: at least 4.5:1.
  2. Headings at 24px+, or 18.66px+ bold: at least 3:1.
  3. Input borders, focus rings, icons and chart lines: at least 3:1 against what's next to them.
  4. Placeholder and helper text: 4.5:1, they aren't exempt.
  5. Text over images: measured against the lightest area behind it.
  6. All states and themes checked.

Frequently asked questions

What contrast ratio does WCAG AA require?

WCAG 2 Level AA requires at least 4.5:1 for normal text and 3:1 for large text (SC 1.4.3), plus 3:1 for user interface components and meaningful graphics (SC 1.4.11).

What counts as large text in WCAG?

Large text is at least 18 point, or at least 14 point if bold. In CSS pixels that is roughly 24px regular or 18.66px bold, because 1pt = 1.333px.

Can I round 4.47:1 up to 4.5:1?

No. The thresholds are minimums with no rounding, so 4.47:1 fails the 4.5:1 requirement. #777777 on white is about 4.48:1 and fails; #767676 on white is about 4.54:1 and passes.

Do logos and disabled buttons need to meet contrast requirements?

No. Text that is part of a logo or brand name is exempt, and so is text in inactive (disabled) components, purely decorative text and text that is not visible to anyone. Placeholder text in an active field is not exempt.

Is APCA required by WCAG?

No. APCA is a contrast method that has been explored in WCAG 3 drafts, and WCAG 3 is still a working draft. Current conformance and most legal requirements are based on WCAG 2.x contrast ratios.

Tools for this guide