What a contrast ratio measures
WCAG 2.2 defines contrast ratio as (L1 + 0.05) / (L2 + 0.05). L1 is the relative luminance of the lighter color and L2 is the relative luminance of the darker color. Because the lighter value always goes on top, the result does not depend on which color is called foreground. The same pair has the same ratio when text and background are swapped.
contrast = (Llighter + 0.05) / (Ldarker + 0.05)
minimum = 1:1
maximum = 21:1Identical colors produce 1:1. Ideal sRGB black against ideal sRGB white produces 21:1. The ratio describes light-and-dark separation, not hue distance: two visibly different hues can still have similar luminance and weak text contrast. This is why choosing complementary colors or moving a hue slider does not prove readability.
How sRGB channels become relative luminance
For an opaque sRGB color, start with the red, green, and blue channel values. Normalize each 8-bit channel from 0–255 to 0–1, linearize it with the sRGB transfer function, and then combine the linear channels. WCAG gives the relative-luminance weighting as 0.2126 for red, 0.7152 for green, and 0.0722 for blue. Green therefore contributes much more to the luminance number than blue.
const linear = value => {
const channel = value / 255;
return channel <= 0.04045
? channel / 12.92
: ((channel + 0.055) / 1.055) ** 2.4;
};
const luminance = (red, green, blue) =>
0.2126 * linear(red) +
0.7152 * linear(green) +
0.0722 * linear(blue);- Parse the final sRGB channels; do not calculate from a color name or visual guess.
- Linearize every channel before applying the luminance weights.
- Calculate both luminances, place the lighter one in L1, and retain enough precision.
- Report a rounded value for humans, but compare the unrounded result with the threshold.
- If transparency or an image is involved, first determine the effective rendered background.
AA and AAA thresholds depend on the text
WCAG Success Criterion 1.4.3 is Level AA. It requires at least 4.5:1 for normal text and at least 3:1 for large-scale text. Success Criterion 1.4.6 is Level AAA: at least 7:1 for normal text and 4.5:1 for large-scale text. The ratio calculation is identical at every level; only the threshold used to interpret it changes.
- AA normal text: 4.5:1 or higher.
- AA large-scale text: 3:1 or higher.
- AAA normal text: 7:1 or higher.
- AAA large-scale text: 4.5:1 or higher.
WCAG defines large-scale as text at least 18 point, or at least 14 point when bold, with equivalent sizing considerations for CJK fonts. CSS pixels and points are not interchangeable labels: in the common CSS reference conversion, 18 pt corresponds to 24 CSS px and 14 pt to about 18.67 CSS px. Weight, the delivered font size, and the actual role of the text must be checked rather than inferred from a screenshot.
Tested pairs and the rounding boundary
The following values use opaque six-digit sRGB colors and the WCAG 2.2 relative-luminance formula. Pass and fail refer to normal text, not large text. Four decimals are displayed so that near-threshold results remain visible.
| Background | Text | Ratio | AA normal | AAA normal |
|---|---|---|---|---|
| White #FFFFFF | Black #000000 | 21.0000:1 | Pass | Pass |
| White #FFFFFF | Gray #767676 | 4.5422:1 | Pass | Fail |
| White #FFFFFF | Gray #777777 | 4.4781:1 | Fail | Fail |
| Aurora Indigo #4F46E5 | White #FFFFFF | 6.2875:1 | Pass | Fail |
| Aurora Indigo #4F46E5 | Black #000000 | 3.3399:1 | Fail | Fail |
| Cyan Horizon #06B6D4 | Black #000000 | 8.6496:1 | Pass | Pass |
#767676 on white passes 4.5:1, while the slightly lighter #777777 does not. A display rounded to one decimal could label both as 4.5:1, but WCAG thresholds are not rounded before evaluation. A computed 4.4781:1 remains below 4.5:1. A reliable checker evaluates the full-precision number and rounds only the label shown to a person.
Transparency, gradients, images, and states
An alpha color has no single contrast ratio until it is composited over a known background. For example, black at 50% opacity becomes a middle gray over white but a much darker result over a pale blue surface. Test the effective rendered foreground against the effective rendered background, not the uncomposited source token. Opacity on a parent can also change both text and its surface.
- For translucent text, composite the text color over every background it can actually cover.
- For gradients, test the lowest-contrast location behind the complete text area.
- For photographs or video, verify representative and worst-case frames; a solid scrim can make the result deterministic.
- Test default, hover, focus, selected, error, and other meaningful states separately when their colors differ.
- Do not sample an antialiased edge pixel as the declared text color; start with the specified foreground and background colors.
Exceptions and requirements this ratio does not cover
The minimum-text criterion has explicit exceptions. Text in an inactive user-interface component, pure decoration, content not visible to anyone, incidental text inside a picture with significant other visual content, and text in a logo or brand name do not receive the same text-contrast requirement under Success Criterion 1.4.3. The exception is narrow: ordinary brand-styled body copy is not a logotype merely because it uses brand colors.
Text contrast is also not the whole color review. User-interface component boundaries and meaningful graphics are addressed by non-text contrast requirements. Links, errors, charts, and statuses must not rely on hue alone when color is the only way to understand the information. Keyboard operation, focus visibility, zoom, reflow, labels, semantics, and alternative text require separate checks.
- Identify whether the content is text, an image of text, a graphical object, or a UI component.
- Use the criterion that matches that content instead of applying 4.5:1 to every pixel.
- Document genuine exceptions, but do not use them to excuse ordinary readable content.
- Treat automated contrast as one deterministic test inside a broader accessibility review.
A repeatable contrast-review checklist
- Capture the final foreground and background in the rendered state being reviewed.
- Resolve CSS variables, named colors, alpha, inheritance, overlays, and blending before calculation.
- Convert the effective sRGB channels to relative luminance with full precision.
- Calculate (L1 + 0.05) / (L2 + 0.05), placing the lighter luminance first.
- Classify the content as normal text, large-scale text, or another type with a different criterion.
- Compare the unrounded result with 4.5, 3, 7, or 4.5 as appropriate.
- Test every materially different state and the lowest-contrast part of variable backgrounds.
- Record the colors, ratio, content class, threshold, result, and date so another reviewer can reproduce it.
- Continue with non-text, interaction, semantic, keyboard, zoom, and human usability checks.
Color Atlas keeps the deterministic pieces separate: stored sRGB values, calculated luminance, an exact ratio, and threshold labels. That structure makes results reproducible and lets a later article compare several candidate text colors against one background without inventing prose or claiming that a number certifies the whole interface.
Primary sources
The factual claims in this article are checked against these published specifications.