Experiment · 2026
Contrast Checker
- Accessibility
- Colour
- Tool
WCAG contrast ratio between any two colours, computed live. Built because I kept opening a web tool for a formula that is four lines long.
Large text, 24px and up
Normal body text at fourteen pixels. This is the size that fails first, and it is the size most of your interface is actually set in.
Contrast ratio 5.48 to 1
01 — WhyWhat made this worth building
Every dark theme I build has one text colour that fails AA at small sizes and passes at large, and I never remember which. Having the maths inline means I check it while I am picking the colour instead of during an audit six weeks later.
02 — NotesHow it works
The contrast ratio is `(L1 + 0.05) / (L2 + 0.05)` where L is relative luminance and L1 is the lighter of the two. The 0.05 term models ambient screen reflection — it is why pure black on pure white tops out at 21:1 rather than infinity.
function luminance({ r, g, b }: RGB) {
const channel = (v: number) => {
const s = v / 255;
// the gamma curve is piecewise: linear near zero, power elsewhere
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
};
return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);
}
function ratio(a: RGB, b: RGB) {
const [hi, lo] = [luminance(a), luminance(b)].sort((x, y) => y - x);
return (hi + 0.05) / (lo + 0.05);
}The thresholds: 4.5:1 for normal text, 3:1 for large text (18.66px bold or 24px regular) and for UI component boundaries. AAA raises those to 7:1 and 4.5:1. Note that WCAG 2 contrast is known to be a poor model for dark themes — APCA is the intended successor. This tool implements WCAG 2 because that is what audits still test against.