Accessibility
WCAG Color Contrast Guide: Ratios, AA vs AAA, and Examples
Contrast ratios are the single best leading indicator of whether your text will be readable to a wide audience. Learn the formula, the AA and AAA thresholds, how large text and non-text contrast work, and the ratios of common color pairs.
Why contrast matters
Roughly one in twelve men and one in two hundred women experience some form of color vision deficiency. A larger group has reduced contrast sensitivity from age, glare, fatigue, low-quality screens, or harsh sunlight on a phone. Color contrast — the relative brightness of text against its background — is the single design decision that affects all of those readers at once.
The Web Content Accessibility Guidelines (WCAG 2.1 and 2.2) define numeric thresholds so the call is not subjective. The home contrast checker implements those thresholds; this page explains what they mean and where they leave room for judgement.
The contrast ratio
Contrast ratio compares the relative luminance of two colors. The ratio runs from 1:1 (identical colors, invisible) to 21:1 (pure black on pure white). The formula:
ratio = (L_lighter + 0.05) / (L_darker + 0.05)
Where L is the relative luminance of each color. Luminance itself is computed by gamma-correcting each RGB channel and then weighting them — green contributes most, then red, then blue:
L = 0.2126 × R + 0.7152 × G + 0.0722 × B
(Channels are first linearised by reversing the sRGB gamma curve — exact steps below.) The takeaway: blue contributes very little to luminance, which is why pure blue text on a black background tests as poor contrast even though it looks "different." It's the same lightness as the background, just a different hue.
The exact relative luminance formula
For an sRGB color with 8-bit channels (0–255), compute each channel separately, then weight them:
for each channel C in R, G, B:
c = C / 255
if c <= 0.04045: c_lin = c / 12.92
else: c_lin = ((c + 0.055) / 1.055) ^ 2.4
L = 0.2126 × R_lin + 0.7152 × G_lin + 0.0722 × B_lin
ratio = (L_lighter + 0.05) / (L_darker + 0.05)
The WCAG 2.x text uses 0.03928 as the threshold instead of the sRGB standard's 0.04045 — it was copied from an older sRGB draft. The difference is harmless: no 8-bit channel value falls between the two (10/255 ≈ 0.0392 and 11/255 ≈ 0.0431), so both versions give identical results for hex colors.
Two more rules from the spec: compare against the threshold without rounding up (4.48:1 fails 4.5:1), and the extra 0.05 in the ratio models ambient flare, which is why the maximum is 21:1 rather than infinity.
The thresholds
| Level | Normal text | Large text | UI components |
|---|---|---|---|
| WCAG 2.1 / 2.2 AA | 4.5 : 1 (SC 1.4.3) | 3 : 1 (SC 1.4.3) | 3 : 1 (SC 1.4.11) |
| WCAG 2.1 / 2.2 AAA | 7 : 1 (SC 1.4.6) | 4.5 : 1 (SC 1.4.6) | — |
"Normal text" is anything below 18pt regular or 14pt bold. "Large text" is at or above those thresholds. "UI components" covers actionable graphical elements — focus rings, icons that carry meaning, the visual edges of inputs. Decorative imagery, logotypes, and inactive UI are exempt.
Large text in pixels
WCAG defines large text in points; CSS uses pixels, and 1pt = 4/3 px:
- 18pt regular = 24px. Text at
font-size: 24pxor larger, at any weight, is large. - 14pt bold ≈ 18.66px. Bold (
font-weight: 700or heavier) text at about 18.66px or larger is large. A 16px bold label is still normal text.
These sizes assume a typical text face. Very thin or decorative fonts read smaller than their nominal size, so give them more contrast, not less.
Non-text contrast (SC 1.4.11)
Added in WCAG 2.1 at level AA, 1.4.11 requires 3:1 against adjacent colors for:
- User interface components: the visual boundary of a text input, a checkbox outline, a toggle's on/off state, a focus indicator, an icon-only button.
- Graphical objects: parts of charts, diagrams and icons that are required to understand the content — e.g. the lines of a line chart, a status icon with no text label.
Not covered: disabled components, logos, decorative graphics, and components whose appearance is entirely browser default. A button whose label passes 4.5:1 doesn't also need a 3:1 border if the label alone identifies it; the requirement is that whatever identifies the component and its state is perceivable.
Which level to target
- AA is the legal floor in many jurisdictions and the realistic target for most consumer products. Hitting AA is a strong baseline.
- AAA is the gold standard, but enforcing 7:1 across an entire color system can flatten brand expression. AAA is most worthwhile on dense reading surfaces — long-form articles, documentation, dashboards with small numeric labels.
- Below AA is appropriate only for incidental or disabled elements (placeholder text becomes readable on focus, decorative text, etc.) — and even then, treat it as a deliberate exception. Placeholder text is not exempt.
Contrast ratios of common color pairs
Computed with the exact formula above and truncated to two decimals (WCAG does not allow rounding up). "Large / UI" is the 3:1 threshold that applies to large text at AA and to non-text contrast.
| Text | Background | Ratio | AA normal | AA large / UI | AAA normal |
|---|---|---|---|---|---|
#FFFFFF | #000000 | 21.00 : 1 | Pass | Pass | Pass |
#000000 | #FFFF00 | 19.55 : 1 | Pass | Pass | Pass |
#333333 | #FFFFFF | 12.63 : 1 | Pass | Pass | Pass |
#595959 | #FFFFFF | 7.00 : 1 | Pass | Pass | Pass |
#000000 | #FFA500 | 10.63 : 1 | Pass | Pass | Pass |
#FFFFFF | #0000FF | 8.59 : 1 | Pass | Pass | Pass |
#FFFFFF | #0066CC | 5.56 : 1 | Pass | Pass | Fail |
#FFFFFF | #008000 | 5.13 : 1 | Pass | Pass | Fail |
#FFFFFF | #D32F2F | 4.97 : 1 | Pass | Pass | Fail |
#FFFFFF | #6C5CE7 | 4.85 : 1 | Pass | Pass | Fail |
#767676 | #FFFFFF | 4.54 : 1 | Pass | Pass | Fail |
#777777 | #FFFFFF | 4.47 : 1 | Fail | Pass | Fail |
#FFFFFF | #FF0000 | 3.99 : 1 | Fail | Pass | Fail |
#FFFFFF | #007BFF | 3.97 : 1 | Fail | Pass | Fail |
#FFFFFF | #808080 | 3.94 : 1 | Fail | Pass | Fail |
#949494 | #FFFFFF | 3.03 : 1 | Fail | Pass | Fail |
#959595 | #FFFFFF | 2.99 : 1 | Fail | Fail | Fail |
#FFFFFF | #1DA1F2 | 2.82 : 1 | Fail | Fail | Fail |
#0000FF | #000000 | 2.44 : 1 | Fail | Fail | Fail |
#FFFFFF | #FFA500 | 1.97 : 1 | Fail | Fail | Fail |
Patterns worth remembering: #767676 is the lightest neutral gray that passes AA on white, and #777777 misses by a hair. #595959 is the lightest gray that passes AAA on white. White on pure red and on Bootstrap-style blue #007BFF is large-text only. Saturated oranges and light blues need dark text, not white. Check any other pair in the contrast checker.
A worked example
Take a button: white text on a brand purple. The brand color is #6C5CE7 = rgb(108, 92, 231). Linearise each channel:
R: 108/255 = 0.4235 → 0.1500
G: 92/255 = 0.3608 → 0.1070
B: 231/255 = 0.9059 → 0.7991
L = 0.2126 × 0.1500 + 0.7152 × 0.1070 + 0.0722 × 0.7991 ≈ 0.1661
White is 1.0. Plug into the ratio:
(1.0 + 0.05) / (0.1661 + 0.05) = 4.86 : 1
4.86 passes AA for normal text (≥ 4.5) but fails AAA for normal text (< 7). For a primary button label that's fine. For 12px helper text on the same background, the message is the same — 4.86 still passes AA — but legibility will start to suffer because contrast minimums alone don't account for tiny type, and the margin above 4.5 is thin.
If the same purple is used as text on a white background, the ratio is identical (the formula is symmetric). But if the background changes to a near-white #F2F2F4, the ratio drops to about 4.35 — now failing AA for normal text, passing only for large text. A barely visible tint on the background was enough to cross the line. If the background changes to mid-gray #9999A0, the ratio drops to about 1.72, which fails everything.
Where the rules surprise people
1. Big numbers can hide small text
WCAG considers a button label "large text" only at 18pt regular or 14pt bold. A 14pt label at regular weight is still "normal text" and needs the full 4.5:1 ratio. Designers regularly design at the borderline weight and assume the looser threshold.
2. Disabled controls are exempt
WCAG explicitly excludes inactive UI components from the 3:1 requirement. That doesn't mean disabled buttons should be invisible — it means the contrast rule doesn't trip a violation. Practical advice: keep disabled affordances visible enough that users understand what's interactive when re-enabled.
3. Logos are exempt
Brand marks and "essential" decorative imagery don't have to meet a contrast ratio. A heritage wordmark on its native background is allowed even if it tests poorly. The exemption does not extend to logo-shaped buttons that carry interactive meaning.
4. Placeholder text is text
The default browser styling for ::placeholder often falls below 4.5:1. If the placeholder communicates anything other than "type here," treat it as normal text and check the contrast.
5. Transparency changes everything
The contrast checker assumes solid colors. The moment alpha is introduced — semi-transparent text or a translucent overlay — the visible color depends on what is behind it. Compute the ratio against the resolved color, not the unblended foreground. The RGBA & transparency guide covers the math.
Beyond the ratio
Hitting 4.5:1 is necessary but not sufficient. Several factors influence real-world readability that the formula doesn't capture:
- Font weight. Hairline weights (200, 300) read worse than the same color at regular weight. If the design uses a thin font, raise the contrast deliberately.
- Anti-aliasing. Sub-pixel rendering on light backgrounds is more forgiving than dark-on-dark, where common rendering settings can leave letterforms looking thin. Bumping body text from 4.5:1 to 7:1 on dark themes pays off.
- Color blindness. Two colors can pass the contrast threshold and still be confusable to a deuteranope (red-green deficiency). Don't rely on color alone to communicate state — pair color with shape, weight, or text labels.
- Ambient light. A dashboard tested at desk light may be unreadable in direct sunlight. Mobile-first products often need higher contrast than the minimum.
A workflow that catches problems early
- Define the palette in tokens, with each pair (text, background) annotated by its tested contrast ratio.
- Pick the smallest text size in the system and validate that the lightest text-on-background combination still passes AA.
- Verify focus indicators against both their default and active backgrounds — the 3:1 rule applies to the focus ring itself.
- Spot-check with the home contrast checker while designing; integrate an automated check (axe-core, Lighthouse) into CI for catching regressions.
- Test the result on a real device under bright light, with a color-blindness simulator, and at the smallest text size in the design.
Common mistakes
- Designing only on a calibrated monitor. Most users don't have one. Build for the worst common case, not the best.
- Using lightness as a proxy for contrast. Two HSL values with the same lightness can differ wildly in luminance. Always use the actual ratio.
- Letting brand color drive body text. Brand colors live in headlines, accents, and large UI. They almost never satisfy 4.5:1 against white, and forcing them to do so produces boring results. Use neutral text colors and let the brand color do the highlighting.
- Treating AAA as a checklist item. Hitting AAA for everything tends to flatten a design. Pick the surfaces that benefit (long-form text, dense data) and target AAA there.
WCAG 2.2, WCAG 3 and APCA
- WCAG 2.2 became a W3C Recommendation in October 2023 and is the current version. Its contrast criteria (1.4.3, 1.4.6, 1.4.11) are unchanged from 2.1, so every ratio on this page applies to both. 2.2 added new criteria about focus, including Focus Appearance (2.4.13, AAA), which asks for a focus indicator with at least 3:1 contrast between its focused and unfocused states.
- WCAG 2.1 AA is still what many regulations reference, including the European standard EN 301 549 and the U.S. Department of Justice's ADA Title II rule. Meeting 2.2 AA also meets 2.1 AA.
- WCAG 3 is a working draft, not a standard. It is expected to change how contrast is measured, and the APCA (Accessible Perceptual Contrast Algorithm) has been explored as a candidate. APCA accounts for polarity (dark-on-light vs light-on-dark), font size and weight, and tends to judge some dark-mode and orange/white pairs differently from WCAG 2. It is not normative: use it as an extra design signal if you like, but measure conformance with the WCAG 2.x ratio.
Where to learn more
The official source is the WCAG 2.2 specification, particularly Success Criterion 1.4.3 (Contrast Minimum), 1.4.6 (Contrast Enhanced) and 1.4.11 (Non-text Contrast). The W3C also publishes detailed Understanding documents that walk through the rationale and exceptions.
Quick reference
- AA: 4.5:1 for body, 3:1 for large text and UI.
- AAA: 7:1 for body, 4.5:1 for large text.
- Normal text = below 18pt (24px) regular / 14pt (≈18.66px) bold.
- Never round up: 4.48:1 fails AA.
- Lightest AA gray on white:
#767676. - Use the actual ratio, not lightness, to judge accessibility.
- Test transparent foregrounds against the resolved color.
- Pair color with another cue so users with color vision deficiency aren't excluded.
Frequently asked questions
What contrast ratio is WCAG AA?
WCAG AA requires at least 4.5:1 for normal text and 3:1 for large text (at least 24px regular or about 18.66px bold). Under success criterion 1.4.11, user interface components and meaningful graphics also need 3:1 against adjacent colors.
What contrast ratio is WCAG AAA?
AAA (success criterion 1.4.6) requires at least 7:1 for normal text and 4.5:1 for large text. AAA adds no stricter requirement for non-text contrast.
What counts as large text in WCAG?
Large text is at least 18 point (24 CSS pixels) at regular weight, or at least 14 point (about 18.66 CSS pixels) when bold. Anything smaller is normal text and needs the 4.5:1 AA ratio.
Is 4.5:1 contrast required for placeholder text?
WCAG has no exemption for placeholder text, so if it is visible text it is held to the same minimum: 4.5:1 for normal-size placeholder text at level AA. Default browser placeholder grays often fail, and automated checkers flag them. Better still, do not rely on placeholders for labels or instructions.
Does color contrast apply to logos?
No. Success criterion 1.4.3 explicitly exempts text that is part of a logo or brand name, and logos are not user interface components under 1.4.11. The exemption does not cover buttons or links that merely use the logo colors.
What is the lightest gray that passes WCAG AA on white?
#767676 is the lightest neutral gray that passes 4.5:1 on white (4.54:1). #777777 is 4.48:1, which fails because WCAG ratios must not be rounded up. For the 3:1 large-text and non-text threshold, the lightest neutral gray is #949494 (3.03:1).
Does white text on red pass WCAG?
White on pure red #FF0000 is 4.00:1. That passes AA only for large text and for UI components, not for normal-size text. A darker red such as #D32F2F reaches 4.98:1 and passes AA for normal text.
Did WCAG 2.2 change the color contrast requirements?
No. WCAG 2.2 became a W3C Recommendation in October 2023 and kept the contrast criteria 1.4.3, 1.4.6 and 1.4.11 unchanged from WCAG 2.1. It added new criteria elsewhere, including focus-related ones.
Is APCA part of WCAG?
No. APCA (Accessible Perceptual Contrast Algorithm) has been explored as a candidate contrast method for WCAG 3, which is still a working draft. It is not normative, and conformance today is measured with the WCAG 2.x contrast ratio.