What a contrast ratio is, and why your eyes are not enough
A WCAG contrast ratio is a single number describing how far apart two colors are in luminance, the amount of light they send to the eye. It runs from 1:1 for two identical colors up to 21:1 for pure black on pure white. This page takes a foreground and a background hex value, computes the ratio, and tells you which WCAG 2.1 thresholds it clears.
The arithmetic is short. Each sRGB channel is normalized, linearized to undo the gamma curve it was encoded with, then weighted and summed into a relative luminance:
L = 0.2126 × R + 0.7152 × G + 0.0722 × B (after sRGB linearization)
ratio = (L1 + 0.05) / (L2 + 0.05), where L1 is the lighter of the two
Those weights are why judging by eye goes wrong. Green carries roughly seven tenths of the luminance and blue less than a fifteenth, so a saturated blue can look bright and energetic while contributing almost nothing to the ratio. Brand blues, purples and reds on white routinely land between 3:1 and 4.5:1, exactly the band where a design looks fine to the person who chose the colors and is hard work for everyone else. The 0.05 added to both sides models ambient light reflecting off the screen, which is why the scale tops out at 21.
The ratio also ignores hue completely. Two colors with identical luminance score 1:1 however different they look, and a pairing can clear 4.5:1 and still vibrate unpleasantly. Contrast is a floor, not a design review.
Which threshold applies to which piece of your interface
- Body text, labels, links, placeholders: 4.5:1. WCAG 2.1 Success Criterion 1.4.3 Contrast (Minimum), Level AA, requires a contrast ratio of at least 4.5:1 for text and images of text. This is the number most policies are asking for.
- Large text: 3:1. The same criterion drops to 3:1 for large scale text, which WCAG 2.1 defines as at least 18 point, or 14 point bold. In CSS that is about 24px, or about 18.66px when the weight is bold, since a CSS point is 1/72 of an inch.
- Enhanced body text: 7:1. Success Criterion 1.4.6 Contrast (Enhanced), Level AAA, requires at least 7:1 for normal text and at least 4.5:1 for large text. Worth targeting for reading-heavy products and older readers.
- Icons, control borders, focus rings, chart lines: 3:1. Success Criterion 1.4.11 Non-text Contrast, Level AA, covers the visual information needed to identify a component and its state, and the parts of a graphic needed to understand the content. Pale 1px input borders are the usual casualty.
- Logos and inactive controls: no requirement. WCAG exempts text in a logo or brand name, text in an inactive user interface component, pure decoration, and text that is part of a picture with significant other visual content. Exempt is not the same as good, so keep disabled labels readable anyway.
- Dark mode: the same numbers, checked separately. A palette that passes on white tells you nothing about it on a dark surface. Test each theme, and each elevated surface within it, since a card lighter than the page moves every ratio on it.
How to check a color pair
- Put the text color in the foreground field and the surface behind it in the background field. Three-digit shorthand such as
#fffworks, and so does the picker beside each field. - Read the big number. Below it, four rows tell you whether the pair clears 4.5, 3, 7 and 4.5 for AA normal, AA large, AAA normal and AAA large text.
- Look at the live preview, which paints your two colors at heading, body and small sizes. A pair that scrapes past 4.5:1 often still looks thin at 13px, which is the point of seeing it rather than only scoring it.
- For an icon or a border, use the icon color as the foreground and whatever sits immediately behind it as the background, then read the 3:1 row instead.
- Repeat for each state that changes color: hover, focus, visited and error.
How to fix a brand color that will not pass
When the foreground fails AA for normal text, this page suggests a replacement: it keeps the hue and saturation, moves only the lightness, and stops at the smallest change that reaches 4.5:1, so the result still reads as the same color. Apply it, or solve it another way:
- Change the background instead. Brand colors are usually fixed while surfaces are not, and a yellow that fails on white passes comfortably on a near-black chip.
- Invert the button. A pale brand color makes a poor text color and a fine fill. Put white or near-black text on it and check that pairing instead, then check the button against the page background for 3:1.
- Promote the text to large scale. At 18 point, or 14 point bold, the requirement falls to 3:1. Legitimate for headlines, a bad idea for anything read in quantity.
- Keep two versions of the brand color. Many design systems ship a marketing color for large surfaces plus a darkened or lightened variant used only for text and icons, which is the standard answer to a brand never designed for screens.
To see the candidate value in other notations, the color converter turns hex into RGB and HSL and back, and pastes straight back into this checker.
Getting colors in, and the verdict out
Most of the work is getting an accurate hex value in the first place. A color read off a screenshot by eye is not the value in your stylesheet, and a wide gamut display shifts it further.
- From a live page: open devtools, select the element, and copy the computed
colorandbackground-color. Computed values already account for inheritance and blending, which is what you want. - From a design file: copy the hex from the fill swatch, not by sampling the canvas, which picks up anti-aliased edge pixels.
- macOS and Windows: Digital Color Meter, in Utilities, reads any pixel on screen; set it to show sRGB values or the number will not match your CSS. PowerToys Color Picker does the same on Windows.
- iPhone and Android: there is no system eyedropper in the browser, so type the hex from your design file. This page works at phone width.
- Sharing the verdict: a screenshot of the number and the pass or fail grid is the fastest thing to drop into a pull request. Quote the criterion, 1.4.3 or 1.4.11, so the reader can look it up.
How other tools compute this, and where they disagree
Every conforming checker uses the same formula, so a disagreement is almost always about the inputs. In JavaScript the whole thing is a dozen lines:
const lin = c => {
const s = c / 255
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4
}
const luminance = ([r, g, b]) =>
0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b)
const ratio = (a, b) => {
const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x)
return (hi + 0.05) / (lo + 0.05)
}
ratio([26, 26, 26], [255, 255, 255]) // 16.1- Browser devtools: the color swatch in the Chrome devtools Styles pane reports the ratio against the detected background with AA and AAA marks, and can draw a threshold line across the color picker. Firefox reports contrast in its Accessibility inspector and gives a range rather than one number for text over an image. Safari shows a ratio in its color picker too. Exact placement moves between releases, so treat this as true at the time of writing.
- Automated audits: Lighthouse and axe both flag insufficient text contrast, and both skip what they cannot resolve, including text over images or gradients and text rendered into a canvas. A clean report is not proof that a page passes 1.4.3.
- Design tools: contrast plugins usually check the selected layer against the one directly behind it, which is wrong whenever a semi-transparent overlay sits between them.
- Wide gamut colors: the WCAG formula is defined on sRGB, so a color written as
color(display-p3 ...)oroklch()has to be converted first, and one outside the sRGB gamut has no exact answer. - The operating system can override you: Windows high contrast themes replace your palette entirely, which CSS sees as
forced-colors, and both Windows and macOS have an increase contrast setting exposed asprefers-contrast. Test those modes too.
Limits, privacy and honest caveats
What leaves your browser: nothing. The two hex values are parsed and divided on your device. No color is uploaded, stored or logged, and the page keeps working offline once loaded.
Two solid colors only. The tool reads hex values and assumes both are fully opaque, so composite any transparency yourself and paste the blended result. It also cannot see your page, so it does not know what is really behind your text.
The 2.x formula has known blind spots. It is widely observed to be harsh on light text over mid-dark backgrounds and generous to very dark pairings, which is the motivation behind APCA and the WCAG 3.0 work. Until that lands in a Recommendation, 4.5:1 and 3:1 are the numbers you will be audited against.
Contrast is one criterion among many. Passing says nothing about font size, line length, hairline weights, or whether color is the only thing telling two states apart, which is a separate criterion. It says nothing about color vision deficiency either, since the formula never looks at hue.
Rounding. Ratios are shown to two decimal places. A pair reported as 4.49 fails and 4.50 passes, so checkers that round differently can disagree at the boundary. If a combination is that close, change it.
Frequently asked questions
What contrast ratio do I need to pass WCAG?
WCAG 2.1 Success Criterion 1.4.3 Contrast (Minimum), Level AA, asks for a contrast ratio of at least 4.5:1 for normal text and at least 3:1 for large text. Success Criterion 1.4.6 Contrast (Enhanced), Level AAA, raises those to 7:1 and 4.5:1. Success Criterion 1.4.11 Non-text Contrast, Level AA, asks for at least 3:1 for user interface components and meaningful graphics.
What counts as large text?
WCAG 2.1 defines large scale text as at least 18 point, or 14 point bold. The Understanding document notes that 18 point is roughly 24px and 14 point bold is roughly 18.66px in CSS, because a CSS point is defined as 1/72 of an inch. Anything smaller than that is normal text and needs the full 4.5:1 at Level AA.
Why does a bright color still fail the check?
The ratio is built from relative luminance, not from how vivid a color looks. After the sRGB values are linearized they are weighted 0.2126 for red, 0.7152 for green and 0.0722 for blue, because human vision is far more sensitive to green light than to blue. A saturated blue can look intense and still carry almost no luminance, so blue on black fails while a duller yellow passes easily.
Should I aim for AA or AAA?
AA is the level most procurement rules, public sector policies and design systems ask for, so treat 4.5:1 as the number you have to hit. AAA is worth targeting for long-form reading, for products used by older people, and for anything safety related. WCAG itself says it is not recommended to require Level AAA conformance across entire sites, because some content cannot reach it.
Do icons, buttons and input borders need contrast too?
Yes. Success Criterion 1.4.11 Non-text Contrast, added in WCAG 2.1 at Level AA, asks for at least 3:1 against adjacent colors for the visual information needed to identify a user interface component and its state, and for parts of graphics needed to understand the content. A 1px light grey input border on white is the classic failure. Put the border color and the background into this tool and read the 3:1 line.
Does disabled or placeholder text have to pass?
WCAG 2.1 exempts text that is part of an inactive user interface component, pure decoration, invisible to everyone, or part of a picture with significant other visual content. Logos and brand names are also exempt. Placeholder text is not exempt, because the field is active, and grey-on-white placeholders are one of the most common failures. Disabled controls pass by exemption but people still have to read them, so do not push them to the floor.
How do I check text sitting on a photo or a gradient?
There is no single background color, so test the worst case: sample the lightest and the darkest pixel under the text and check both. If either fails, the usual fixes are a solid or semi-opaque scrim behind the text, a text shadow strong enough to separate the glyphs, or moving the text to a flat area. Automated scanners often skip these cases entirely rather than report them.
What do I do with semi-transparent colors?
Flatten them first. A ratio is only defined between two solid colors, so a foreground at 60 percent opacity has to be composited over whatever is actually behind it before you can test it. Take the blended value from your browser devtools, which report the computed color, and paste that hex here. Testing the unblended color will make a failing combination look like it passes.
Is APCA better, and what changed in WCAG 2.2?
WCAG 2.2 did not change the contrast criteria, so 1.4.3 and 1.4.6 still use the same formula and the same 4.5:1, 3:1 and 7:1 thresholds this page reports. APCA is a perceptual contrast algorithm developed as research toward WCAG 3.0, and it does model dark interfaces better than the 2.x formula, but it has not been adopted in a W3C Recommendation. Conform with 2.x, then use APCA as a second opinion.
Does anything I type here leave my browser?
No. The two hex values are parsed, linearized and divided on your device in a few lines of JavaScript, and no color is uploaded, stored or logged. That also means the page works offline once it has loaded, and you can safely test unreleased brand colors on it.
Sources
- W3C, Web Content Accessibility Guidelines (WCAG) 2.1 for Success Criterion 1.4.3 Contrast (Minimum) at 4.5:1 and 3:1, 1.4.6 Contrast (Enhanced) at 7:1 and 4.5:1, 1.4.11 Non-text Contrast at 3:1, the exemptions for logotypes and inactive components, and the definitions of contrast ratio, relative luminance and large scale text as at least 18 point or 14 point bold.
- W3C, Web Content Accessibility Guidelines (WCAG) 2.2, which carries the same contrast criteria and thresholds forward unchanged.
- W3C, CSS Color Module Level 4 for hex notation, the sRGB color space and the wider gamuts that have to be converted to sRGB before the WCAG weights apply.
- Devtools behavior in Chrome, Firefox and Safari, and the coverage of automated audits, is described from the shipping versions at the time of writing and moves between releases.
More tools
To convert a candidate value between hex, RGB and HSL, or to walk a hue through several lightness steps before bringing it back here, use the color converter. If you are auditing a component library rather than a single pair, the regex tester is a quick way to pull every hex literal out of a stylesheet so you can work through them.
Related tools
- Color Converter (HEX, RGB, HSL)
Convert colors between HEX, RGB and HSL instantly, with a built-in color picker, live prev…
- Regex Tester
Test a regular expression against sample text and see every match, capture group and posit…
- JSON Formatter and Validator
Pretty-print or minify JSON in your browser with 2-space, 4-space or tab indentation.
- Base64 Encode and Decode
Convert text to Base64 and back with full UTF-8 support, so accented letters, CJK and emoj…
- QR Code Generator (SVG & PNG)
Turn a link, text or Wi-Fi login into a QR code and download it as SVG or PNG.
- Word Counter & Character Count
Count words, characters with and without spaces, sentences and paragraphs as you type.
Privacy: both colors are parsed and compared in your browser, and nothing is sent to a server, stored or logged. No analytics event carries the colors you enter.
