Check contrast. Fix it. Share it.
Understanding WCAG Contrast Levels
Requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text (18px bold or 24px regular). This is the standard most websites and apps are expected to meet for legal and accessibility compliance.
Requires a contrast ratio of at least 7:1 for normal text and 4.5:1 for large text. This is the highest WCAG level, recommended for critical content and long-form reading. Not always required for full conformance, but significantly improves readability.
The Accessible Perceptual Contrast Algorithm is the proposed replacement for WCAG 2.x contrast math. Instead of a single ratio, APCA produces a lightness contrast (Lc) value that accounts for polarity (light-on-dark vs. dark-on-light) and correlates more closely with perceived readability. Minimum Lc values depend on font size and weight.
Contrast standards reference: WCAG 2.x and APCA thresholds, formulas, disagreements
The checker above computes WCAG 2.x ratio and APCA Lc for any color pair. The reference below covers the math behind both algorithms, every published threshold, the disagreement zones where the two metrics give opposite verdicts, and the legal landscape that decides which one applies to your project.
Algorithm summary
| Property | WCAG 2.x | APCA |
|---|---|---|
| Spec status | W3C Recommendation since WCAG 2.0 (2008); current at 2.2 (Oct 2023) | Candidate algorithm in WCAG 3.0 working draft |
| Author | W3C Web Content Accessibility Guidelines Working Group | Andrew Somers, Inclusive Reading Technologies |
| Output | Contrast ratio, 1:1 to 21:1 | Signed Lc value, roughly −108 to +106 |
| Polarity aware | No (same number whether dark on light or light on dark) | Yes (sign encodes polarity) |
| Font size aware | Binary (normal vs “large”) | Continuous (size and weight shift the threshold) |
| Color space | sRGB with piecewise gamma decode | sRGB with soft clamp on near-black values |
| Reference implementation | Formula is the spec; many libraries | apca-w3 (npm), pinned to a published commit |
| Legal binding | EAA, Section 508, ADA Title II all reference WCAG 2.x | None |
WCAG 2.x AA and AAA thresholds
| Content type | Level AA | Level AAA |
|---|---|---|
| Normal text (under 18pt regular, under 14pt bold) | 4.5:1 | 7:1 |
| Large text (18pt+ regular, 14pt+ bold) | 3:1 | 4.5:1 |
| UI components (button outlines, form borders, focus rings) | 3:1 | n/a |
| Graphical objects conveying information | 3:1 | n/a |
| Logo or brand-mark text | Exempt | Exempt |
| Decorative or inactive UI | No floor | No floor |
CSS pixel equivalents at 96 DPI: 18pt is about 24px regular; 14pt bold is about 18.66px bold. “Large” requires both size and weight to clear the bar at once. SC 1.4.3 covers text contrast. SC 1.4.11 covers non-text contrast. SC 2.4.11, new in WCAG 2.2, governs focus indicator appearance.
APCA Bronze Simple body-text lookup
Minimum Lc by font size and weight, taken from the W3C APCA Readability Criterion Bronze Simple Mode table. Apply the absolute value of Lc when checking against the threshold; the sign encodes polarity only.
| Font size | Weight 400 (regular) | Weight 500 (medium) | Weight 700 (bold) |
|---|---|---|---|
| 14px | n/a | n/a | Lc 90 |
| 16px | Lc 75 | Lc 70 | Lc 60 |
| 18px | Lc 70 | Lc 65 | Lc 55 |
| 24px | Lc 55 | Lc 50 | Lc 40 |
| 32px | n/a | n/a | Lc 30 |
Non-body-text APCA thresholds:
| Use | Lc minimum |
|---|---|
| Non-text UI (focus indicators, button outlines, icon strokes) | 45 |
| Spot reading (copyright footer, fine print) | 30 |
| Decorative (logo marks, divider rules) | No floor |
Bronze Lc 60 at 16px is acceptable only at weight 700. The body-copy floor at weight 400 is Lc 75, which is why mid-grays on white that pass WCAG 2.x AA often fail APCA.
Where the two algorithms disagree
Test vectors with paired verdicts. All cells paired with the listed background. APCA column references Lc 75 (16px regular) as the body floor.
| Foreground | Background | WCAG ratio | WCAG AA normal | APCA Lc | APCA 16px regular |
|---|---|---|---|---|---|
| #767676 | #FFFFFF | 4.54:1 | Pass | 53 | Fail |
| #595959 | #FFFFFF | 7.00:1 | Pass | 73 | Borderline |
| #4D4D4D | #FFFFFF | 8.59:1 | Pass | 81 | Pass |
| #949494 | #FFFFFF | 3.04:1 | Fail | 40 | Fail |
| #6BA8E8 | #FFFFFF | 2.48:1 | Fail | 47 | Fail |
| #1F5EAE | #FFFFFF | 4.51:1 | Pass | 71 | Borderline |
| #000000 | #FFEE00 | 18.0:1 | Pass | 97 | Pass |
| #000000 | #00C896 | 11.7:1 | Pass | 81 | Pass |
| #FFFFFF | #4A4A4A | 8.50:1 | Pass | −78 | Passreversed |
| #FFFFFF | #6A6A6A | 4.83:1 | Pass | −60 | Failreversed |
The shape of the disagreement: WCAG is more forgiving on mid-gray text in the 4.5 to 6.0 ratio band. APCA is more forgiving on saturated yellows and greens because its luminance weighting is closer to ITU-R BT.709 than to the WCAG 2.x weights. Reverse polarity is where APCA gets strictest, since thin strokes lose effective contrast against dark backgrounds and the algorithm penalizes that explicitly.
Decision matrix: which standard applies
Pick the row that matches your project. The “Binding” column is what an auditor or regulator reaches for. The “Run alongside” column is what to add for your own quality bar.
| Project type | Binding | Run alongside |
|---|---|---|
| EU public sector or in-scope private (EAA, Jun 2025) | WCAG 2.2 AA via EN 301 549 | APCA on mid-gray body text |
| US federal site or federal vendor (Section 508) | WCAG 2.0 AA | WCAG 2.2 AA on new builds |
| US state and local government (ADA Title II, Apr 2024 rule) | WCAG 2.1 AA | WCAG 2.2 AA on new builds |
| US private web product, no regulated industry | No legal floor; WCAG 2.x AA is industry default | APCA in design tokens |
| Internal design system, no statutory exposure | Your choice | Both metrics for token validation |
| iOS or Android app shipping to platform store | WCAG 2.1 AA (HIG and Material reference) | Platform-specific guidance |
| WCAG 3.0 forward-looking research | APCA Bronze | WCAG 2.2 as floor |
EAA enforcement allows fines up to €3M per violation in some member states. Section 508 violations affect federal procurement eligibility rather than producing direct fines. ADA Title II compliance dates: large public entities by April 2026, smaller entities by April 2027.
Under the hood: how the math works
WCAG 2.x contrast ratio uses CIE relative luminance with a piecewise sRGB gamma decode.
For each sRGB channel value c normalized to [0, 1]:
c_linear = c / 12.92 if c <= 0.03928 c_linear = ((c + 0.055) / 1.055) ^ 2.4 otherwise
Relative luminance:
L = 0.2126 * R_linear + 0.7152 * G_linear + 0.0722 * B_linear
Contrast ratio:
ratio = (L_brighter + 0.05) / (L_darker + 0.05)
The 0.05 offset is a flare term modeling display surface reflection. Polarity blindness comes from sorting by brightness before dividing.
APCA Lc generation applies a soft clamp on near-black values, uses a luminance weighting closer to ITU-R BT.709 (0.2126, 0.7152, 0.0722 with different gamma), raises L to a power (0.56 for text, 0.57 for non-text), takes the signed difference between text and background, and scales by 1.14 to land in a 0-to-100-ish range. The signed difference preserves polarity. The published reference implementation is apca-w3 on npm.
sRGB gamma decode lookup
Quick mental math for which channel dominates luminance. Linear values are after gamma decode; contribution at full G is the linear value times 0.7152.
| sRGB byte (0–255) | Linear value | Contribution at full G |
|---|---|---|
| 0 | 0.00000 | 0.000 |
| 32 | 0.01030 | 0.007 |
| 64 | 0.05126 | 0.037 |
| 96 | 0.12744 | 0.091 |
| 128 | 0.21586 | 0.154 |
| 160 | 0.31855 | 0.228 |
| 192 | 0.45641 | 0.327 |
| 224 | 0.65017 | 0.465 |
| 255 | 1.00000 | 0.715 |
Saturated green at byte 192 contributes 0.327 to luminance. Saturated red at the same byte contributes 0.097. Saturated blue contributes 0.033. This is why bright yellows and greens lift WCAG ratios sharply and saturated blues barely move them.
Standards landscape
| Standard | Year | Bound by | Status |
|---|---|---|---|
| WCAG 2.0 | 2008 | Section 508 (2018 refresh) | Stable, superseded for new audits |
| WCAG 2.1 | 2018 | EN 301 549 v3.2, ADA Title II Apr 2024 | Currently binding in EU and US state/local |
| WCAG 2.2 | Oct 2023 | EN 301 549 next update | Current Recommendation; adds SC 2.4.11 |
| WCAG 3.0 working draft | In progress | None | Editor’s Draft only; expected post-2027 |
| APCA Readability Criterion | Candidate in WCAG 3 | None | Draft; version pinned by apca-w3 |
| EN 301 549 v3.2.1 | 2021 | EU procurement, EAA reference | Current EU baseline |
| ISO/IEC 40500 | 2012 | International mirror of WCAG 2.0 | Superseded |
| Section 508 (Revised) | 2018 | US federal procurement | Current |
Common pitfalls
| Symptom | Cause | Fix |
|---|---|---|
| Same pair gives different ratios in two tools | Gamma decode precision; channel rounding | Differences under 0.05 are noise; ignore |
| AAA badge on a heading, normal-text badge fails on subtitle below it | Subtitle is normal text, not large text | Check at 16px regular for the subtitle, not at heading size |
| Pair passes WCAG on swatch, looks unreadable in production | Subpixel rendering on thin weights at small sizes | Bump weight from 400 to 500 before re-checking |
| Tooltip at 70% opacity reports very high WCAG ratio | Measuring raw foreground, not composited foreground | Composite against the actual background first, then measure |
| Dark-mode pair at 4.6:1 passes AA but feels harder to read | Reverse polarity penalty; APCA flags this | Target Lc 75 absolute for body in dark mode |
| Focus indicator at 1px and 2.8:1 fails audit | SC 2.4.11 requires 2 CSS px thickness and 3:1 contrast | Increase ring to 2px and check contrast against adjacent background, not just the button |
Related concepts
- Relative luminance vs perceived lightness: WCAG uses Y from CIE XYZ. APCA uses a perceptual L closer to CIELAB L*. The two diverge most for mid-grays.
- OKLCH color space: Perceptually uniform space useful when adjusting lightness without shifting hue. Recommended for auto-fix routines that need to preserve brand identity through a lightness adjustment.
- EAA scope: Covers e-commerce, banking, transport ticketing, audiovisual media services, e-readers. Excludes micro-enterprises (under 10 employees and €2M turnover) in most member-state implementations.
- Images of text: SC 1.4.5 limits images of text; an image with valid alt text shifts the contrast obligation to the alt text channel, not the rendered pixels.
- WCAG 3.0 timeline: Editor’s Draft as of 2026; W3C Recommendation track typically takes 18 to 24 months past Candidate Recommendation. Production binding before 2028 is unlikely.