Home · Methodology
Methodology — Check Our Arithmetic
Every verdict on this site comes from one measurement, computed one way, everywhere. This page publishes the formula, the thresholds, the rounding rule and the hand-computed test vectors the measurement must reproduce — so any expert can verify the site against its own record.
The formula (WCAG 2.1)
For each 8-bit channel: c = c8/255; linearise as c/12.92 when c <= 0.04045, otherwise ((c + 0.055)/1.055)^2.4. Luminance L = 0.2126 R + 0.7152 G + 0.0722 B over the linearised channels. Ratio = (L lighter + 0.05) / (L darker + 0.05). Verdicts compare the unrounded ratio with the threshold; the two-decimal display is never used for the verdict.
The thresholds, by use
| Use | Minimum ratio | Criterion |
|---|---|---|
| Normal text — AA | 4.5:1 | WCAG 2.1 §1.4.3 |
| Large text — AA | 3:1 | WCAG 2.1 §1.4.3 |
| Normal text — AAA | 7:1 | WCAG 2.1 §1.4.6 |
| Large text — AAA | 4.5:1 | WCAG 2.1 §1.4.6 |
| Non-text: components, boundaries, focus indicators, meaningful graphics — against the adjacent colour | 3:1 | WCAG 2.1 §1.4.11 |
Large text — Large text is at least 24px (18 point), or at least 18.66px (14 point) at bold weight (700 or heavier). Nothing else counts as large, however big it looks.
The rounding rule. Verdicts compare the unrounded ratio with the threshold. The two-decimal figure shown anywhere on this site is display only and is never reused for a verdict. A ratio of 4.496170 therefore fails AA normal text while displaying as "4.50". This is the standard's own position — the ratio is not rounded up to meet a criterion — and it is the rule most likely to be quietly broken by other tools.
The test record — hand-computed vectors
Before any of this site's measurement code was written, the vectors below were computed by hand from the formula above, channel by channel, and spot-checked against published reference values for the same pairs (the #767676 pair is the canonical 4.54 example). The shipped measurement must reproduce every ratio to the fourth decimal and every verdict exactly; the suite runs against the live build, and a single disagreement fails it.
| Pair | Exact ratio | Displays as | Verdict the measurement must return |
|---|---|---|---|
| #000000 on #FFFFFF | 21.000000 | 21.00 | Passes everything |
| #FFFFFF on #FFFFFF | 1.000000 | 1.00 | Fails everything |
| #767676 on #FFFFFF | 4.542225 | 4.54 | AA normal PASS · AAA FAIL |
| #2563EB on #FFFFFF | 5.168556 | 5.17 | AA normal PASS · AAA FAIL |
| #808080 on #FFFFFF | 3.949440 | 3.95 | AA normal FAIL · AA large + non-text PASS |
| #647A87 on #FFFFFF | 4.491467 | 4.49 | AA normal FAIL |
| #767776 on #FFFFFF — the trap | 4.496170 | 4.50 | AA normal FAIL — display rounding must never promote it |
| #E5E7EB on #111827 (dark theme) | 14.328285 | 14.33 | AA + AAA PASS |
| #3B82F6 on #FFFFFF (before repair) | 3.677901 | 3.68 | AA normal FAIL · the repair case in the guide below |
One point of record about the repair vector: an earlier draft of this site's specification named #2563EB as the colour a lightness-only repair of #3B82F6 would land on. Measured in OKLCH, the two colours differ in chroma and sit 3.07° apart in hue, so no lightness-only move can arrive there; the repair as defined lands on #2B72E5 at 4.524816, hue held, verdict recomputed from the final hex. The error was in the draft's worked example, not in the arithmetic above — #2563EB's own ratio (5.168556) is correct and asserted in the suite. The correction is recorded here rather than quietly rewritten, because a test record you cannot trust is worse than none.
How generation and repair use the measurement
Generation works in OKLCH: a role colour is found by walking its lightness along the brand hue, converting each candidate to hex, and measuring that hex against the actual adjacent colours until the role's threshold clears. Repair uses the same walk in the other direction: lightness only, hue held, chroma reduced only when the sRGB gamut forces it (with a note), and the verdict always recomputed from the final hex — never from the OKLCH target, which can round across a boundary. Alpha inputs are composited over a background the visitor specifies, or refused with an explanation; transparency is never silently ignored. Colour-vision simulation uses the Machado et al. (2009) matrices and is a warning layer only — it never changes a verdict.
APCA, stated honestly
Shown as a labelled second opinion only. APCA has no normative status today; every verdict on this site is decided by WCAG 2.1. Where a page shows an APCA Lc value, it is labelled a second opinion in those words. The APCA vs WCAG guide explains the disagreement between the methods without taking the draft's side.
What this site does not do
It does not certify WCAG conformance, EAA compliance or ADA compliance, for any palette or product; contrast ratios are evidence for one criterion family. It is not affiliated with the W3C, WebAIM or any enforcement body — standards are cited, dated, and left owned by their authors. It publishes no usage statistics, ratings or testimonials, because it has none to publish.