WCAG Color Contrast Ratio Explained: AA vs AAA
Low-contrast text is one of the most common accessibility failures on the web, and one of the cheapest to catch. Light gray on white is the classic offender: it looks refined in a mockup and becomes a squint on a phone in daylight. The Web Content Accessibility Guidelines (WCAG) turn "enough contrast" into a number you can test, which means you never have to argue about it by eye.
What a contrast ratio measures
WCAG compares the relative luminance of two colors: roughly, how bright each one is as the human eye perceives it, on a scale from 0 (black) to 1 (white). The ratio is:
(L1 + 0.05) / (L2 + 0.05)
where L1 is the lighter color's luminance and L2 the darker one's. The 0.05 stops the math from blowing up near black. The result runs from 1:1 (identical colors, invisible text) to 21:1 (pure black on pure white).
Relative luminance is not just an average of red, green and blue. Green contributes far more to perceived brightness than red, and red more than blue, and the values are first converted out of the screen's gamma curve. That is why two colors with similar-looking hex codes can have very different contrast ratios, and why guessing is unreliable.
The thresholds that matter
- 4.5:1 is the minimum for normal-size text at WCAG level AA. This is the baseline most laws and organizational policies point to.
- 3:1 is the AA minimum for large text: roughly 18 point (24 pixels) or bigger, or 14 point (about 18.7 pixels) and bold. Big, heavy letters are easier to distinguish.
- 7:1 is the stricter AAA level for normal text (4.5:1 for large), aimed at low-vision readers and difficult viewing conditions.
- 3:1 is also the minimum for user-interface components and meaningful graphics under WCAG 2.1: input borders, focus rings, chart lines and icons that carry information.
Purely decorative elements and logos are exempt, as is disabled UI. Placeholder text is not automatically exempt, which catches a lot of forms out.
How to check a color pair
- Open the Color Converter.
- Enter your text color and your background color as HEX, RGB or HSL. The tool converts between the three.
- Read the ratio and the three verdicts: AA normal text, AA large text and AAA normal text.
- If the pair fails, darken the text (or lighten the background) a step at a time and re-check until it passes. Keep the hue and adjust only the lightness to preserve your brand color.
- Repeat for every state: hover, disabled-looking-but-readable, error messages, text over gradients and text over images.
A quick benchmark worth memorizing: #767676 on white is about 4.5:1, the lightest neutral gray that passes AA for body text. #999999 on white is about 2.8:1 and fails. If your "subtle" gray is lighter than #767676, it fails on white.
Why this matters beyond compliance
Low contrast does not only affect people with diagnosed vision impairments. It affects anyone reading on a low-quality screen, in bright sunlight, with the brightness turned down to save battery, or simply tired at the end of the day. A design that looks fine on a calibrated monitor in a dim office can be nearly unreadable in the conditions most people actually use their phones. Meeting AA also lowers legal risk, since many accessibility laws and procurement requirements reference WCAG 2.x AA.
Where typical contrast checkers fall short
Browser developer tools will show a ratio for text on a page, and they are great for checking a live site. But a lot of web-based contrast checkers want a sign-up, load slowly under ads, or only check one pair at a time with no conversion between color formats, which is a nuisance when your design file uses HSL and your CSS uses HEX. The MergeDoc Color Converter does the conversion and the contrast math together in the browser, with no upload and no account.
Its limits matter. It evaluates two flat colors. It does not sample text over a photo or gradient, it does not account for semi-transparent colors, and it does not measure the newer APCA model that some design teams are experimenting with, which gives different answers. For text on images, test the worst-case spot where the text overlaps the lightest or darkest part of the picture.
Everyday uses
- Choosing a brand palette. Check text, button and link colors against each background before the brand guide is finalized.
- Fixing a design handoff. Verify the designer's gray caption text before developers implement it.
- Auditing a site. Check the footer links, placeholder text and form error messages, which are the usual suspects.
- Building a dark mode. Contrast needs re-checking: a color that passes on white may fail on near-black.
- Preparing a presentation. Slides are read from the back of rooms with projectors that wash out light colors.
Tips and mistakes to avoid
Do not rely on color alone to carry meaning. A red error with no icon or text label is invisible to some color-blind users. Use the Color Blindness Simulator to preview how an image or interface appears under the common deficiencies, and add a second cue such as an icon, underline or text.
Check hover and focus states separately. A link that passes at rest can fail when the hover color is lighter.
Do not forget text sizes. A pair that passes at 3:1 only qualifies if the text really is large or bold-large. Body copy at 16 pixels needs 4.5:1.
Pulling a palette from a photograph? The Color Palette Extractor finds dominant colors, but extracted colors are not guaranteed to be readable together, so run each text and background pairing through the checker.
Last, treat the ratio as a floor. Passing 4.5:1 by a hair on a small light-weight font can still be tiring. If you can comfortably go higher, do.
A worked example
Suppose your caption text is #888888 on a white background. Convert each channel to linear light and weight them: the gray works out to a relative luminance of about 0.25, and white is exactly 1. The ratio is (1 + 0.05) / (0.25 + 0.05) = 1.05 / 0.30 = about 3.5:1. That passes the large-text threshold of 3:1 but fails the 4.5:1 needed for normal body text. Darken the gray to #767676 and the ratio rises to roughly 4.5:1, enough for AA.
The same logic works in reverse for light text on dark. White on #767676 gives about 4.5:1, so mid-gray backgrounds are an awkward zone where neither black nor white text is especially comfortable. Check both before you commit to one.
Where WCAG contrast has limits
The WCAG 2.x formula is simple and widely required, but it is not perfect. It treats light-on-dark and dark-on-light symmetrically, which does not match how people actually perceive them, and it ignores font weight and size beyond the single large-text switch. Some teams also test against the proposed APCA model for a second opinion. Use the WCAG ratio as your compliance baseline, since that is what audits and laws reference, and use your own eyes on a real phone as the final check. A pair that scores 4.6:1 in a thin 12-pixel font may still be poor to read.
If you are working to a deadline, prioritize in this order: body text, links, form labels and error messages, then buttons and icons, then decorative text. Fixing those first covers the content people actually need to read and click. Record the approved color pairs in your design tokens so developers reuse them instead of picking a new gray each time.
Related reading
Contrast is the visual half of readability. The textual half is covered in Flesch Reading Ease Explained. For design-side utilities, CSS Gradients, Shadows and Border Radius shows how to build effects that keep text legible, and Resize Images Without Losing Quality covers preparing the graphics that sit behind it. The developer tools category holds the rest of the toolbox.
Frequently asked questions
- What contrast ratio does WCAG AA require?
- At least 4.5:1 for normal-size text and 3:1 for large text. Large means roughly 18 point (24 pixels) and up, or 14 point (about 18.7 pixels) and up if bold. Level AAA raises these to 7:1 and 4.5:1.
- How is the WCAG contrast ratio calculated?
- It is (L1 + 0.05) / (L2 + 0.05), where L1 is the relative luminance of the lighter color and L2 of the darker, each on a 0 to 1 scale. The result runs from 1:1 (no contrast) to 21:1 (black on white).
- Is gray text on a white background accessible?
- Only if it is dark enough. #767676 on white is about 4.5:1, the lightest gray that passes AA for body text. #999999 on white is about 2.8:1 and fails.
- Do icons and buttons need contrast too?
- Yes. WCAG 2.1 asks for at least 3:1 for user interface components and meaningful graphics, such as the border of an input field or an icon that carries information.
- Does passing contrast mean my design is accessible?
- No. Contrast is one requirement among many. Also check that color is not the only way information is shown, test with color blindness in mind, and make sure text remains readable when zoomed or in dark mode.
- Does the Color Converter check contrast for any two colors?
- Yes. Enter a foreground and a background color and it shows the ratio plus pass or fail for AA normal text, AA large text and AAA normal text. It calculates from the exact colors you give it, so check each state of a design, not just the default.
Tools mentioned
More in Developer Tools
Related posts
SHA-256 Hash Explained: What It Is and When to Use It
What a SHA-256 hash is, why one changed letter changes everything, how it differs from encryption, and how to generate SHA hashes free in your browser.
Unix Timestamps Explained: Epoch Time to Date and Back
What a Unix timestamp is, why it starts in 1970, seconds versus milliseconds, time zones, and the 2038 problem. Convert epoch time free in your browser.
CSS Gradients, Shadows and Border Radius, Explained
Learn the syntax behind linear-gradient, box-shadow and border-radius, with the values to start from and free generators to preview and copy the CSS.