Two colours have a contrast ratio only as a pair, and the number an audit turns on is the WCAG 2 one. This page reports it beside an APCA score, because the two disagree hardest on exactly the light-on-dark pairs interfaces are built from now. When a level fails, text and background get separate suggestions, since one of the two is usually already fixed by a brand and the tool cannot know which.
The ratio is a luminance quotient, and green is 72% of luminance
The WCAG 2 contrast ratio is (L1 + 0.05) / (L2 + 0.05), where L1 is the relative luminance of the lighter colour and L2 of the darker. Relative luminance takes each 8-bit sRGB channel, divides by 255, undoes the display transfer curve, and weights the three results 0.2126 red, 0.7152 green, 0.0722 blue. Those weights are most of what the number measures: #00ff00 on black scores 15.3:1 while #0000ff on black scores 2.4:1, because the eye takes almost all of its luminance signal from green and almost none from blue. The two 0.05 terms stand in for light reflecting off the screen in an average room, and they are also what caps the scale at 21:1, black on white. The definitions are in WCAG 2.2 and are unchanged from WCAG 2.0.
The ratio is symmetric because the formula sorts the two luminances before dividing. Swapping text and background returns exactly the same number, which is why this page offers a swap button rather than two separate readings: the WCAG verdicts do not move, and the APCA score and the preview do. A colour with alpha is composited onto what is behind it before any of this runs, since a translucent colour has no luminance of its own.
The WCAG 2 formula is unreliable on dark backgrounds
WCAG 2's ratio flatters light text on dark backgrounds, and the pair loaded by default here is the demonstration: #9aa0a6 on #202124 is Google's own dark-theme secondary text on its own dark surface. It scores 6.10:1, clearing AA at 4.5:1 with room to spare, and at 14px it reads as grey mush. APCA puts the same pair at Lc -48, well under the Lc 75 it asks for body text.
Two things cause it. The formula is a ratio rather than a difference, so at the dark end the fixed 0.05 flare term dominates both halves and small luminance differences inflate into large ratios. And perceived contrast is not symmetric the way the arithmetic is: a light glyph on a dark field blooms at its edges, which gets worse with astigmatism and with the thin weights dark interfaces favour. WCAG 2 has no notion of font weight either, so a 300-weight and a 700-weight label at the same size get the identical verdict.
What APCA changes, and what it does not
APCA, the Accessible Perceptual Contrast Algorithm, is a different measurement rather than a rescaled ratio. It is perceptual, fitted to reported readability instead of derived from a luminance quotient. It is polarity aware: apca(text, background) is not symmetric, and the sign records which way round the pair is, negative for light text on dark. And it is weight and size aware, publishing the Lc each size and weight needs rather than one number for all text. #767676 on white is Lc 71.6; white on #767676 is Lc -77.0. WCAG scores both pairs at 4.54:1. An Lc is not a ratio: the scale runs to about 106, and Lc 60 is neither 60:1 nor convertible to one. The figures here are revision 0.1.9, constant set G-4g, which matters because Lc values move between revisions.
The honest limitation: APCA is informative and is not a WCAG 2 conformance criterion. It is a candidate method for WCAG 3, a Working Draft with no normative status and no publication date, so nothing legal or contractual rests on an Lc today. An audit against WCAG 2.0, 2.1 or 2.2, and so against EN 301 549, Section 508 and the European Accessibility Act, is settled by the ratio alone. Ship the ratio. Read the Lc when the ratio passes and the text still looks wrong, which is the case it exists for.
Large text means 18.66px bold or 24px regular
This is the most misread line in the criterion. WCAG defines large-scale text as at least 18 point, or 14 point bold, and at the CSS reference resolution of 96dpi those are 24px and 18.66px. It is a measurement, not a role: a 24px regular subhead qualifies and needs only 3:1 at AA, while an 18px bold one does not qualify and needs the full 4.5:1. Calling an element a heading has no bearing on it. Two of the preview rows above are set at exactly those sizes; the preview runs five because the criterion distinguishes two and your eye distinguishes all five.
Why this tool uses 0.03928 and not 0.04045
The threshold in the published WCAG text for switching between the linear and power segments of the sRGB transfer curve is 0.03928, and it is the wrong number. The segments actually meet at 0.04045; the smaller value is a rounding artefact from an early sRGB draft that was never corrected in the WCAG prose. It moves luminance only for channels in a sliver near 10/255, far too little to turn a pass into a fail. This tool uses the published 0.03928 on purpose, so its ratios match what an auditor computing from the specification gets. When another checker disagrees in the third decimal on a very dark colour, that is usually why.
Common problems
- It passes and it still looks wrong. Check the polarity badge. If it is light on dark, read the Lc: that is exactly where the ratio is least trustworthy, and the fix is usually a heavier weight or a lighter text colour rather than a darker background.
- The text sits on an image, a gradient or a video. There is no single background colour, so test the worst one: the lightest pixel the text crosses if the text is light, the darkest if the text is dark. A scrim behind the text is the usual fix.
- Placeholder text is not exempt. The 1.4.3 exceptions cover incidental text, logotypes and inactive controls. A placeholder in an enabled input is live text held to 4.5:1, which is why so many grey placeholders fail an audit.
- Icons and borders are a different rule. Non-text contrast is 1.4.11, added in WCAG 2.1, and it asks 3:1 of icons, input borders, focus rings and chart keys against what is next to them. Test those pairs here against the 3:1 row.
- The suggestion does not look like your brand colour. It holds hue and chroma and moves only OKLCH lightness, the axis contrast depends on. If the shift still reads as a different colour, the pair is far enough from passing that something other than the text colour has to give.
Frequently asked questions
Is 4.5:1 actually enough?
It is the legal floor, not a target. 4.5:1 was chosen to cover roughly 20/40 visual acuity, about the loss typical at age 80, and it assumes a healthy display in reasonable light. AAA asks 7:1 of the same text. For 16px body copy, treat 4.5:1 as the point below which you have a defect and something nearer 7:1 as the point above which nobody complains.
Did WCAG 2.2 change any of these numbers?
No. Success criteria 1.4.3 (Contrast Minimum, AA) and 1.4.6 (Contrast Enhanced, AAA) are unchanged from WCAG 2.0 in 2008 through 2.1 in 2018 and 2.2 in 2023. WCAG 2.2 added focus and target-size criteria and removed 4.1.1 Parsing; it left the contrast arithmetic exactly where it was. The next change to it is WCAG 3, which is years out.
Does it matter which colour I enter first?
Not for the ratio, which is symmetric, and very much for everything else. The APCA score changes sign and magnitude, the preview draws a different pair, and the suggestions move a different colour. Enter them as they appear on screen and use the swap button to see the other polarity.
How do I check a whole palette rather than a pair?
Test the pairs you will ship, not the matrix of everything against everything: body text on each surface, muted text on each surface, and each interactive colour on the surface it appears on. Run the pairs that carry meaning through the colour blindness simulator too. Contrast and hue discrimination are separate problems, and a pair can pass one and fail the other.
Does anything I enter leave my browser?
No. The luminance, the ratio, the APCA score and the lightness search all run in this tab, with no request to send them anywhere. The two colours ride in the ?fg= and ?bg= parameters only so a link reproduces what you are looking at. The colour format converter and the rest of the colour tools work the same way.