WCAG Color Contrast: A Developer's Quick Guide
Learn WCAG contrast ratio requirements for AA and AAA compliance. Understand how to check, fix, and design accessible color combinations for text, buttons, and UI elements.
Try our free Color Converter
Check WCAG contrast ratios between any two colors with our built-in accessibility checker.
Why Color Contrast Matters
Color contrast is the difference in perceived brightness between two colors. When text doesn't have enough contrast against its background, it becomes difficult or impossible to read for millions of users. Approximately 1 in 12 men and 1 in 200 women have some form of color vision deficiency, and an even larger number of people deal with situational impairments like screen glare, low-brightness settings, or aging eyesight.
Beyond accessibility, poor contrast directly impacts usability for everyone. A user reading your content on a phone in bright sunlight, a developer working late with tired eyes, or someone using a low-quality monitor all benefit from strong color contrast. Studies show that improved readability increases time on page, reduces bounce rates, and leads to higher conversion rates.
The Web Content Accessibility Guidelines (WCAG), published by the W3C, define specific contrast ratios that text and UI elements must meet. These guidelines are not just best practices — they are legal requirements in many jurisdictions, including the ADA in the United States, the Equality Act in the UK, and the European Accessibility Act. Failing to meet these standards can expose organizations to lawsuits and regulatory penalties.
WCAG Contrast Ratio Requirements
WCAG 2.1 defines contrast requirements across two success criteria. The contrast ratio is expressed as a value between 1:1 (no contrast, like white on white) and 21:1 (maximum contrast, black on white).
Success Criterion 1.4.3 — Contrast (Minimum) — Level AA
- - Normal text: minimum contrast ratio of 4.5:1
- - Large text: minimum contrast ratio of 3:1
- - Incidental text: text that is part of a disabled component, purely decorative, or not visible has no contrast requirement
Success Criterion 1.4.6 — Contrast (Enhanced) — Level AAA
- - Normal text: minimum contrast ratio of 7:1
- - Large text: minimum contrast ratio of 4.5:1
Success Criterion 1.4.11 — Non-text Contrast — Level AA
- - UI components and graphical objects: minimum contrast ratio of 3:1 against adjacent colors
What counts as "large text"? WCAG defines it as text that is at least 18 points (24px) regular weight or 14 points (approximately 18.66px, commonly rounded to 18px) bold weight. Large text gets a lower contrast threshold because bigger characters have thicker strokes, making them inherently easier to distinguish from the background.
AA vs AAA Compliance
WCAG defines three conformance levels: A (minimum), AA (mid-range), and AAA (highest). Most legal requirements and industry standards target Level AA, which is considered the practical standard for web accessibility.
| Element | AA Ratio | AAA Ratio |
|---|---|---|
| Normal text (<18px bold / <24px regular) | 4.5:1 | 7:1 |
| Large text (≥18px bold / ≥24px regular) | 3:1 | 4.5:1 |
| UI components (buttons, inputs, icons) | 3:1 | — |
Which level should you target? For most projects, AA is the right goal. It provides a strong baseline of accessibility without overly constraining your design palette. AAA is ideal for content-heavy sites like government portals, healthcare applications, and educational platforms where readability is paramount. Keep in mind that achieving AAA for an entire site can be challenging — even WCAG itself notes that it is not always possible for all content.
A practical approach: aim for AA across all text, and target AAA for body copy and critical UI elements like error messages, navigation labels, and form instructions. Use our Color Converter to check both AA and AAA compliance for any color pair.
How to Calculate Contrast Ratios
The contrast ratio formula compares the relative luminance of two colors. Relative luminance is a measure of how bright a color appears to the human eye, normalized on a scale from 0 (black) to 1 (white).
Step 1: Calculate Relative Luminance
For each color, convert sRGB values (0-255) to linear RGB, then apply the luminance formula:
// Convert 8-bit sRGB to linear value
function linearize(channel) {
const sRGB = channel / 255;
return sRGB <= 0.04045
? sRGB / 12.92
: Math.pow((sRGB + 0.055) / 1.055, 2.4);
}
// Calculate relative luminance (ITU-R BT.709)
function luminance(r, g, b) {
const R = linearize(r);
const G = linearize(g);
const B = linearize(b);
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
}The coefficients (0.2126, 0.7152, 0.0722) reflect human vision — our eyes are most sensitive to green, then red, then blue. This is why pure green (#00FF00) appears much brighter than pure blue (#0000FF) despite having the same intensity value.
Step 2: Calculate the Contrast Ratio
function contrastRatio(color1, color2) {
const L1 = luminance(color1.r, color1.g, color1.b);
const L2 = luminance(color2.r, color2.g, color2.b);
const lighter = Math.max(L1, L2);
const darker = Math.min(L1, L2);
return (lighter + 0.05) / (darker + 0.05);
}
// Example: black (#000000) vs white (#FFFFFF)
// L1 = 1, L2 = 0
// Ratio = (1 + 0.05) / (0 + 0.05) = 21:1The 0.05 offset prevents division by zero and accounts for ambient light. You don't need to implement this yourself — tools like our Color Converter calculate contrast ratios instantly. But understanding the formula helps you intuit why certain color combinations fail.
Common Contrast Mistakes
Even experienced designers and developers fall into these contrast traps. Here are the most frequent offenders:
1. Light Gray Text on White Background
#999999 on #FFFFFF — ratio 2.85:1Fix: Use #595959 or darker for body text on white (ratio 7.1:1). For secondary text, #767676 is the lightest gray that passes AA at 4.54:1.
2. Yellow or Light Green on White
#FFFF00 on #FFFFFF — ratio 1.07:1Fix: Yellow is almost invisible on white. Use a dark gold (#8B6914) or pair yellow with a dark background instead.
3. Placeholder Text That Disappears
#C0C0C0 placeholder on #FFFFFF — ratio 1.61:1Fix: Placeholder text should meet at least 4.5:1 contrast. Use #767676 or darker. Better yet, use floating labels that remain visible after input.
4. Low-contrast Links Without Underlines
#6699CC links on #FFFFFF without underline — ratio 3.01:1Fix: Links must have 3:1 contrast against surrounding text AND 4.5:1 against the background, or use a non-color indicator like an underline.
5. Thin Font Weights Reducing Perceived Contrast
font-weight: 300 at small sizes on colored backgroundsFix: Thin fonts have less visible area per character, making contrast appear lower than calculated. Use font-weight 400 or higher for body text, especially at sizes below 16px.
A good rule of thumb: if you have to squint or lean closer to read the text, the contrast is too low. Test your color combinations using the WCAG checker in our Color Converter. You can also use our CSS Unit Converter to ensure your font sizes are meeting the "large text" threshold in the correct unit.
Building an Accessible Color Palette
Designing with accessibility from the start is far easier than retrofitting it later. Here is a systematic approach to building a color palette that passes WCAG requirements:
1. Start with Your Brand Colors
Take your primary brand color and generate a full shade scale (50 through 950). For each shade, calculate the contrast ratio against both white (#FFFFFF) and black (#000000). Mark the "crossover point" where the color transitions from being readable on a light background to needing a dark background. This crossover typically happens around the 500-600 range for most hues.
2. Designate Text Colors with Clear Rules
- - Primary text: should meet AAA (7:1) against the background. On white, use #1A1A1A to #333333.
- - Secondary text: should meet AA (4.5:1) at minimum. On white, #767676 is the lightest acceptable gray.
- - Disabled text: exempt from contrast requirements, but should still be distinguishable from enabled states. Around 2:1 is conventional.
3. Test Every Combination
Don't just test text against the page background — test against cards, modals, tooltips, banners, and hover states. A color that passes on a white page may fail on a light gray card (#F5F5F5). Create a contrast matrix that maps every foreground color against every background it will appear on.
4. Account for Dark Mode
If your app supports dark mode, you need a separate set of contrast checks. Colors that work on light backgrounds often fail on dark ones and vice versa. Define separate semantic color tokens for light and dark themes, and verify each independently.
5. Use Semantic Color Tokens
Instead of hard-coding hex values throughout your CSS, use design tokens like --color-text-primary, --color-text-secondary, and --color-bg-surface. This lets you update contrast-safe values in a single place. You can test how different colors render as CSS gradients using our CSS Gradient Generator to ensure gradient backgrounds maintain sufficient contrast with overlaid text.
Frequently Asked Questions
What contrast ratio do I need for WCAG AA?
What counts as 'large text' in WCAG?
Is white text on a colored background accessible?
Do contrast requirements apply to UI components like buttons?
Check Your Color Contrast
Enter any two colors and instantly see the WCAG contrast ratio, AA/AAA pass/fail status, and accessible alternatives. Free, private, runs in your browser.
Open Color Converter