Tutorial
How to fix insufficient colour contrast
In short
Normal text needs a contrast ratio of at least 4.5:1 against its background; large text (from 24px, or 18.66px bold) at least 3:1. Graphical elements and interface states (borders, icons, focus) need at least 3:1. Measure the ratio with a contrast checker and darken the colour until the value passes.
At a glance
Measure the ratio
Check the foreground and background colour with a contrast checker and read the ratio.
Pick the threshold
4.5:1 for normal text, 3:1 for large text (from 24px or 18.66px bold).
Adjust the colour
Darken the text or strengthen the background until the value meets the threshold.
Check UI elements
Borders, icons and focus indicators also need at least 3:1 (1.4.11).
Insufficient contrast is by far the most common automatically measurable failure. It affects more than blind users: in sunlight, on cheap displays or with age-related low vision, light grey text on white becomes unreadable. The upside: contrast is a hard, deterministically measurable criterion.
The thresholds
| Content | Minimum (AA) |
|---|---|
| Normal text (< 24px, or < 18.66px bold) | 4.5:1 |
| Large text (from 24px, or from 18.66px bold) | 3:1 |
| Graphics and interface elements (borders, icons, focus) | 3:1 |
The problem
/* #999999 auf #ffffff = 2.85:1 -> faellt durch (Minimum 4.5:1) */
.text {
color: #999999;
background: #ffffff;
}
/* Button-Rand kaum sichtbar: #e2e2e2 auf #ffffff = 1.2:1 */
.btn {
color: #ffffff;
background: #ffffff;
border: 1px solid #e2e2e2;
}#999999 on white is only 2.85:1, well below 4.5:1. The button has a border, but at 1.2:1 it is effectively invisible: it fails 1.4.11 (Non-text Contrast).
The fix
/* #595959 auf #ffffff = 7:1 -> besteht deutlich */
.text {
color: #595959;
background: #ffffff;
}
/* Fuellung UND Rand tragen jetzt Kontrast:
Text #ffffff auf #1d4ed8 = 6.3:1, Rand vs. Umgebung >= 3:1 (1.4.11) */
.btn {
color: #ffffff;
background: #1d4ed8;
border: 1px solid #1d4ed8;
}#595959 on white is 7:1, well above the threshold. The button now carries a high-contrast fill, so both the text and the shape itself are perceivable.
Measuring correctly
- Measure the actually rendered colours, not the design tokens: transparency and stacked layers change the result.
- Text over an image is the special case: contrast varies across the image. Put a solid layer or gradient behind the text.
- Thin type (font-weight 300) reads with less contrast than the raw number suggests: darken it when in doubt.
Percelia measures contrast on the rendered DOM including CSS, reports every shortfall with the exact colour and ratio, and can route the borderline case over an image to human review.
Related WCAG criteria
Frequently asked questions
- What counts as large text?
- From 24px regular or from 18.66px (14pt) bold. Large text only needs 3:1 instead of 4.5:1.
- Does contrast apply to disabled elements?
- No. Text in inactive (disabled) controls is exempt from 1.4.3. Active buttons, links and normal text must meet the threshold.
- Is exactly 4.5:1 good enough?
- Yes, exactly 4.5:1 passes. We still recommend a little headroom, because rendered colours can shift slightly through antialiasing and displays.
Request a free scan
Tell us your domain — we run a free initial scan and show you the most important barriers.