1.4.3 Contrast (Minimum)
Text and images of text have a contrast ratio of at least 4.5:1, except for large text which requires 3:1.
What This Rule Means
WCAG 1.4.3 establishes minimum contrast requirements between foreground text and its background. Normal-sized text (below 18pt or 14pt bold) must achieve a contrast ratio of at least 4.5:1. Large text (18pt / 24px and above, or 14pt / 18.66px bold and above) requires a minimum of 3:1. These ratios are calculated using relative luminance values defined in the WCAG contrast algorithm.
The criterion covers all text content rendered on screen, including text in images, placeholder text in form fields, text over images or gradients, and text generated by CSS. Exceptions exist for incidental text (decorative text, inactive UI components, logos, and brand names) where the text is not expected to be read by the general audience.
This is one of the most frequently failed WCAG criteria and one of the most impactful to fix. Contrast is measurable, automatable, and directly affects readability for a large portion of users with low vision, aging eyes, or suboptimal viewing conditions.
Why It Matters
Low-contrast text is one of the most common accessibility barriers on the web. According to the WebAIM Million report, low contrast is consistently the number one automatically detected accessibility error, appearing on over 80% of home pages analyzed. This affects not only the estimated 246 million people worldwide with moderate-to-severe visual impairment but also every user who has ever squinted at light gray text on a white background.
Contrast is not only a disability concern. Environmental factors like bright sunlight, dimmed screens for battery saving, projectors in meeting rooms, and low-quality displays all reduce the effective contrast a user perceives. A contrast ratio of 4.5:1 provides a reasonable safety margin for all these conditions.
For users with low vision who do not use screen readers, text contrast can be the difference between independently reading content and being unable to use a website at all. Unlike some accessibility requirements that benefit a narrow group, good contrast benefits virtually everyone.
Related axe-core Rules
- color-contrast — Checks that the foreground and background color combination of text elements meets the minimum 4.5:1 ratio for normal text and 3:1 for large text. This is one of the most commonly triggered axe rules.
The color-contrast rule examines computed styles, accounting for inheritance, opacity, and background colors. It flags elements where contrast falls below the threshold and reports the actual ratio alongside the required ratio.
How to Test
- Run axe DevTools or the Lighthouse accessibility audit — both flag contrast failures with specific ratio values and element locations.
- Use the browser DevTools color picker, which in Chrome and Firefox shows the contrast ratio when you inspect a text element's color property.
- Use dedicated contrast checkers like the WebAIM Contrast Checker or the Colour Contrast Analyser (CCA) desktop app for manual verification.
- Test text over images or gradients by checking contrast at the lowest-contrast point of the background.
- Verify placeholder text contrast. Though not technically required by 1.4.3, placeholders used as labels must meet the ratio.
- Check contrast in all states: default, hover, focus, active, disabled. Disabled states are exempt, but other interactive states must meet the ratio.
- Test with Windows High Contrast Mode and macOS Increase Contrast setting to verify text remains readable.
How to Fix
Start by establishing a contrast-safe color palette during the design phase. Define primary, secondary, and accent colors that pass 4.5:1 against your background:
/* Contrast-safe color system */
:root {
/* Background */
--bg-primary: #ffffff;
--bg-secondary: #f8f9fa;
/* Text — all pass 4.5:1 against --bg-primary */
--text-primary: #1a1a2e; /* 16.15:1 */
--text-secondary: #4a4a68; /* 7.24:1 */
--text-muted: #646480; /* 4.98:1 */
/* Interactive — pass 4.5:1 against white */
--link-color: #0055b8; /* 7.04:1 */
--link-hover: #003d82; /* 10.5:1 */
/* Status colors — pass 4.5:1 against white */
--color-error: #c62828; /* 6.15:1 */
--color-success: #1b5e20; /* 7.82:1 */
}
For text over images, use an overlay or text shadow to guarantee minimum contrast:
/* Semi-transparent overlay on image backgrounds */
.hero-overlay {
position: relative;
}
.hero-overlay::after {
content: "";
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.6);
}
.hero-overlay .text {
position: relative;
z-index: 1;
color: #ffffff;
}
/* Alternative: text shadow for readability */
.text-on-image {
color: #ffffff;
text-shadow:
0 1px 3px rgba(0, 0, 0, 0.8),
0 0 8px rgba(0, 0, 0, 0.5);
}
Fix common patterns like light gray placeholder text:
/* Default placeholder is often too light (#a9a9a9 = 2.32:1 on white) */
input::placeholder {
color: #646480; /* 4.98:1 against white */
}
/* Ensure focus ring color also has sufficient contrast */
input:focus {
outline: 3px solid #0055b8;
outline-offset: 2px;
}
Handle dynamic themes and dark mode by defining contrast-safe values for each scheme:
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #121212;
--bg-secondary: #1e1e2e;
--text-primary: #e0e0e8; /* 13.2:1 against #121212 */
--text-secondary: #a8a8c0; /* 7.1:1 */
--text-muted: #8888a0; /* 4.63:1 */
--link-color: #6eb5ff; /* 7.52:1 */
}
}
For large text (18pt/24px regular or 14pt/18.66px bold), the threshold drops to 3:1, which allows more design flexibility:
.page-title {
font-size: 2rem; /* 32px = large text */
font-weight: 700;
color: #666688; /* 4.18:1 — passes 3:1 for large text */
}
.body-text {
font-size: 1rem; /* 16px = normal text */
color: #4a4a68; /* 7.24:1 — passes 4.5:1 for normal text */
}
Common Mistakes
- Light gray text on white backgrounds — the most pervasive contrast failure on the web. Colors like #999 on #fff yield only 2.85:1.
- Brand colors chosen without accessibility review. A brand blue of #4A90D9 on white is only 3.27:1 — fails for normal text.
- White text on hero images without an overlay. Contrast varies across the image, often falling below thresholds in lighter regions.
- Placeholder text styled too lightly. Browser defaults for ::placeholder often fail contrast requirements.
- Forgetting about interactive states: hover and focus text colors that reduce contrast below the minimum.
- Using CSS opacity on text elements, which effectively reduces contrast by blending with the background.
- Assuming that dark mode is automatically accessible — dark-on-dark failures are equally common as light-on-light.