🎨 CSS

CSS Color Contrast Checker

Compare a foreground and background color and see the real WCAG 2.1 contrast ratio with AA/AAA pass or fail badges.

21.00:1
Normal Text AA (4.5:1)
Normal Text AAA (7:1)
Large Text AA (3:1)
Large Text AAA (4.5:1)
UI Components AA (3:1)
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.

About the CSS Color Contrast Checker

Contrast here is calculated with the same relative luminance formula the WCAG 2.1 guidelines use: each channel gets gamma-corrected, weighted, and summed, then the lighter luminance is compared against the darker one. A ratio of 21:1 means the two colors are as far apart as black and white can get, while 1:1 means they're identical and unreadable against each other. The pass/fail badges mirror the thresholds testers actually check during an accessibility audit, from small body copy up to large bold headings and UI control borders.

Why each color channel gets "gamma-corrected" before anything else

The raw 0-255 red, green, and blue values in a hex color don't map linearly to how bright a pixel actually appears on screen, sRGB displays apply a gamma curve, so a value of 128 isn't perceived as exactly half as bright as 255. Before this tool can meaningfully combine the channels, it converts each one from 0-255 down to a 0-1 fraction, then applies the WCAG-specified correction: values at or below 0.03928 are treated as linear (divided by 12.92), while everything above that follows a power curve, ((c + 0.055) / 1.055) ^ 2.4. This reverses the display's gamma encoding and gives back the color's true linear light output, which is what needs to be compared for an accurate perceptual contrast measurement.

Why green is weighted far more heavily than blue

The final luminance sum is 0.2126 × red + 0.7152 × green + 0.0722 × blue, weights that look arbitrary but come directly from how human vision actually works. The eye's cone cells are far more sensitive to green wavelengths than to blue, so a pure green pixel reads as much "brighter" to a human than a pure blue pixel of the same raw intensity, even though both are mathematically "255" in their channel. These specific coefficients come from the ITU-R BT.709 standard used for HDTV and sRGB, and they're why a color contrast checker can't just average R, G, and B equally and get an accurate result.

What the +0.05 in the ratio formula is doing

The contrast ratio formula is (L1 + 0.05) / (L2 + 0.05), where L1 is the lighter color's luminance and L2 is the darker one's. That added 0.05 to both sides exists mainly to avoid a divide-by-zero and to model the reality that even a "pure black" display pixel reflects a small amount of ambient light rather than truly emitting zero luminance. It's this constant that produces the familiar maximum ratio of exactly 21:1 for true black against true white, rather than an undefined or infinite result.

Why "large text" and "UI components" get an easier 3:1 threshold

WCAG doesn't apply one universal contrast minimum, it scales the requirement to how easy the content already is to read. "Large text" is formally defined as 18pt (24px) regular weight or 14pt (about 18.7px) bold or larger, since bigger, heavier strokes remain legible at lower contrast than small body copy does, so it only needs 3:1 at AA instead of 4.5:1. UI components, like input borders, checkbox outlines, and icon buttons, fall under a separate WCAG 2.1 success criterion (1.4.11, Non-text Contrast) that also uses a 3:1 minimum, reflecting that a control's boundary doesn't need text-reading-level precision to be usable, just enough definition to be visually locatable.

A real limitation: this checker assumes fully opaque colors

Both the foreground and background inputs are treated as fully opaque hex colors. In real interfaces, text is sometimes rendered over a semi-transparent background layer (an overlay, a frosted-glass card, an rgba() fill), and in that case the effective contrast depends on whatever color shows through beneath it, which this tool has no way to know or account for. If your actual design uses transparency, you'll need to first flatten the visible result (calculate what color the transparent layer produces against its real backdrop) and test that flattened color here instead.

Frequently Asked Questions

Why does this tool "gamma-correct" the RGB values before comparing colors?

Raw 0-255 RGB values don't map linearly to perceived brightness on an sRGB display. Gamma-correcting each channel converts it back to true linear light output, which is required by the WCAG formula for an accurate perceptual luminance comparison, matching a raw hex value directly would give inaccurate results.

Why is green weighted so much more heavily than blue in the luminance formula?

The weights (0.2126 red, 0.7152 green, 0.0722 blue) come from how sensitive human cone cells actually are to each wavelength. Human eyes perceive green as far brighter than blue at equal raw intensity, so an accurate luminance formula must weight the channels unequally to match real visual perception.

What's the maximum possible contrast ratio, and when does it occur?

21:1, which occurs only between pure black (#000000) and pure white (#ffffff). It's the theoretical ceiling of the WCAG contrast formula, any other pair of colors will produce a ratio somewhere below that maximum.

Why do large text and UI components only need a 3:1 ratio instead of 4.5:1?

WCAG scales its contrast requirement to how readable content already is. Large text (18pt+ regular or 14pt+ bold) remains legible at lower contrast because of its bigger, heavier strokes, and UI component boundaries fall under a separate criterion (1.4.11) that only requires enough contrast to be visually locatable, not text-reading precision.

Does this tool account for semi-transparent colors?

No, both colors are treated as fully opaque. If your real design uses a transparent overlay or rgba() background, you'll need to first determine the flattened, fully-opaque color that transparency actually produces against its backdrop, then test that resulting color here.

Can I type a 3-digit shorthand hex code like #fff instead of the full 6 digits?

Yes, the hex input accepts 3-digit shorthand codes and automatically expands each digit to its doubled 6-digit equivalent (so #fff becomes #ffffff) before calculating luminance, matching how browsers interpret shorthand hex colors in CSS.