Requires text to have a contrast ratio of at least 4.5:1 against its background, or 3:1 for large text, so people with low vision or color deficiencies can read it.
Light gray text on a white background looks elegant on a designer's bright monitor. For a person with low vision, a color deficiency, a cataract, an older screen or a phone in sunlight, it is unreadable.
This criterion requires a contrast ratio of at least 4.5:1 between text and its background. Large text, which is at least 24 px, or at least 18.66 px and bold, needs at least 3:1. The ratio is calculated from the relative luminance of the two colors. It runs from 1:1 (no contrast) to 21:1 (black on white).
People with low vision, color vision differences and age-related vision changes need contrast to read. Anyone who uses a screen in bright light, a low quality display or a small phone also benefits. High contrast is easier for people with dyslexia and for people who tire easily. It also makes content easier to read for everyone.
The European Accessibility Act (Directive (EU) 2019/882) applies to in-scope products and services placed on the market after 28 June 2025. Recital 47 names four principles for websites and mobile applications: perceivable, operable, understandable and robust. Readable contrast is part of "perceivable".
The technical counterpart is the standard EN 301 549, which incorporates WCAG 1.4.3 by reference and turns it into separate clauses for each kind of ICT.
| Clause | Type of ICT | What it requires |
|---|---|---|
| 9.1.4.3 | Web pages | Web content must satisfy WCAG success criterion 1.4.3. |
| 10.1.4.3 | Non-web documents (PDF, Office files) | The same criterion applies to the text colors in documents. |
| 11.1.4.3 | Non-web software (native mobile apps) | Software that supports screen readers must satisfy the criterion. |
Clause numbers follow the "9. + WCAG number" pattern of EN 301 549. In V3.2.1 the software clause is divided into further subclauses for open and closed functionality. Check the exact numbers in the standard when you cite them.
Standard version: EN 301 549 V4.1.1 (September 2026) is based on WCAG 2.2 and is the first version prepared specifically for the EAA. It has not yet been cited in the Official Journal of the European Union, so for now it is best treated as a voluntary technical route to the EAA's requirements. Once cited, it will give a presumption of conformity. The text of criterion 1.4.3 is the same in WCAG 2.1 and 2.2. It is a Level AA criterion.
A note on EAA scope: Article 2(4) of the Directive excludes certain content from the requirements, for example office file formats published before 28 June 2025 and archives that are not updated after that date. Content you publish or change after that date is not covered by these exclusions.
Directive (EU) 2019/882, EUR-Lex, opens in a new tab
Light gray text looks good but fails. #767676 on white is the lightest gray that passes for normal text.
body { color: #999999; background: #ffffff; } /* 2.85:1, fails */body { color: #595959; background: #ffffff; } /* 7.0:1 */
/* #767676 on white is 4.54:1, the lightest gray that passes */Large text only needs 3:1. A color that fails for body text may pass for a large heading.
.note { color: #888888; font-size: 16px; } /* 3.54:1, fails: normal text */h1 { color: #888888; font-size: 32px; } /* 3.54:1, passes: large text */
.note { color: #595959; font-size: 16px; } /* 7.0:1 */White text on a light brand color often fails. Darken the background until the ratio is enough.
.btn { background: #4caf50; color: #ffffff; } /* 2.78:1, fails */.btn { background: #2e7d32; color: #ffffff; } /* 5.13:1 */Placeholder text is text. It needs the same ratio.
::placeholder { color: #aaaaaa; } /* 2.32:1, fails */::placeholder { color: #6b6b6b; } /* 5.33:1 */Check the worst point behind the text. A dark overlay or a solid background behind the text makes the ratio predictable.
.hero { background: url(photo.jpg); }
.hero h2 { color: #ffffff; }.hero { background: url(photo.jpg); }
.hero h2 {
color: #ffffff;
background: rgba(0, 0, 0, 0.7);
padding: 8px 12px;
}Check the hover, focus and visited colors as well as the default one.
a { color: #0066cc; }
a:visited { color: #b8a9d9; } /* fails on white */a { color: #0066cc; } /* 5.57:1 */
a:visited { color: #6b3fa0; } /* passes on white */
a:hover { color: #003d7a; } /* passes on white */The same rule applies in native mobile apps. Use system colors or color tokens whose ratios you have checked in both light and dark mode.
import SwiftUI
struct PriceLabel: View {
var body: some View {
VStack(alignment: .leading, spacing: 8) {
// Avoid: a custom light gray (about 2.85:1 on white)
// Text("Total").foregroundColor(Color(hex: 0x999999))
// Use semantic colors, which adapt to dark mode
Text("Total")
.foregroundStyle(.secondary)
// Or a checked token
Text("€42.00")
.foregroundStyle(Color("TextPrimary")) // 7:1 on the background
}
}
}import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
@Composable
fun PriceLabel() {
// Avoid: a custom light gray (about 2.85:1 on white)
// Text("Total", color = Color(0xFF999999))
// Use theme colors whose pairs you have checked in light and dark themes
Text(
text = "Total",
color = MaterialTheme.colorScheme.onSurfaceVariant
)
// Or a checked color (5.62:1 on white)
Text(
text = "Payment failed",
color = Color(0xFFC62828)
)
}