Web Developmenteditorial12 min read

APCA and WCAG: Two Ways to Measure Readability

WCAG 2.x contrast ratios are the legal baseline. APCA models perceived lightness differently. Know which to use when.

A designer passed QA with four point six to one contrast on every text pair. A stakeholder with low vision still could not read the muted caption. The ratio was mathematically correct under WCAG 2.2. The experience was not. Compliance had been satisfied. Comprehension had not. That gap is why two contrast models coexist in professional interface work, and why teams that treat a single number as destiny keep shipping captions that audits bless and humans strain to parse at twelve pixels on a laptop in afternoon glare.

WCAG 2.x contrast ratios remain the legal and contractual baseline in most jurisdictions. APCA, the Advanced Perceptual Contrast Algorithm, offers a perceptual model that better tracks how humans read text on screens, especially at small sizes, low weights, and on saturated backgrounds. Neither replaces the other today. Understanding both, and when each one lies to you, is part of shipping interfaces that are defensible in audit and usable in practice. The goal is not two numbers on a spreadsheet. It is stakeholders who passed QA actually reading the caption without zooming the browser.

What WCAG 2.x actually measures

WCAG Success Criterion 1.4.3 Contrast Minimum and its large-text sibling 1.4.11 do not measure readability directly. They measure a contrast ratio derived from relative luminance, a single number per color with hue largely stripped out. For sRGB values normalized to zero through one, each channel undergoes gamma removal, then relative luminance L combines channels with weights 0.2126, 0.7152, and 0.0722. The contrast ratio between a lighter color L1 and darker L2 is L1 plus 0.05 divided by L2 plus 0.05, where L1 is the higher luminance. The ratio is symmetric. Swapping foreground and background yields the same number. That symmetry is simple to implement and audit. It is also a weakness, because perception does not treat light-on-dark and dark-on-light identically at the same absolute difference.

Under WCAG 2.2 Level AA, normal text requires four point five to one. Large text requires three to one. UI components and graphical objects require three to one. Large text means at least eighteen point regular, or fourteen point bold, though practice varies on whether six hundred weight counts as bold for audit purposes. Our contrast checker implements this model because compliance conversations, procurement language, and automated scanners reference it. When a client statement of work cites WCAG 2.1 AA or WCAG 2.2 AA, this is the math being invoked.

The formula has no input for font size beyond the large versus normal binary. It has no input for font weight beyond the bold threshold for large text. It has no input for anti-aliasing, subpixel rendering, or font design. A twelve pixel light-weight caption and a forty-eight pixel heavy display headline are evaluated with the same ratio threshold if both count as normal or large. Hue is theoretically ignored, but human vision is not. Red on green at equal luminance can pass WCAG while failing for color-blind users, which is why WCAG also includes criteria about not conveying information by color alone. Relative luminance struggles with highly chromatic backgrounds. A saturated blue panel can yield a passing ratio for white text while letters appear to vibrate against the field.

What APCA adds to the conversation

APCA was developed by Andrew Somers and collaborators as part of research feeding into WCAG 3 work under the W3C Silver Task Force. The Visual Contrast of Text Subgroup documented APCA as a candidate method for a future conformance model. WCAG 3 remains draft. APCA is not a legal substitute for WCAG 2.x ratios in contracts today. Treat APCA as a design-system tutor, not an exemption letter.

APCA returns Lc, lightness contrast, a signed value typically ranging from roughly negative one hundred eight to positive one hundred six. Positive Lc means dark text on a light background. Negative Lc means light text on a dark background. The sign matters because human contrast sensitivity is not symmetric across polarity. Lc incorporates perceptual lightness via a luminance model tuned for self-illuminated displays, text size in pixels or points with accounting for x-height where provided, font weight from one hundred through nine hundred, and text purpose in advanced calculators. The Myndex APCA calculator is the reference implementation most practitioners use. Third-party tools may ship older APCA constants. Note the version when documenting tests.

Unlike WCAG’s two-tier system, APCA uses a matrix of minimum Lc values. Exact numbers evolve with APCA versions. The table below reflects commonly cited APCA 0.98G body-text targets used in production discussions. Always verify against the calculator version you ship with.

Use case Approx. minimum Lc
Fluent body text (16px, 400) 75
14px body (400) 80
12px captions (400) 85–90
18px+ display (400) 60
24px+ headlines (700) 45–55

An Lc of seventy-five is not seventy-five percent. It is an index on a perceptual scale. Compare pairs consistently with the same font metrics and the same polarity you actually ship. A pair that returns Lc seventy-eight for dark-on-light may return a different magnitude light-on-dark. Test the polarity on the live theme.

When the two models disagree

Consider a muted secondary text token at oklch lightness 0.55 chroma 0.02 on a near-white surface at oklch 0.98. WCAG reports roughly four point six to one, an AA pass for normal text. At thirteen pixels regular weight in a data table, users report strain. APCA often scores this pair in the low seventies Lc, below the roughly eighty target for that size. The ratio said yes. Perception said no. Saturated backgrounds produce similar splits. Brand blue with white text can exceed four point five to one while APCA penalizes the chromatic contrast interaction, especially for smaller type. Designers perceive glow or vibration that luminance ratio never sees.

Thin weights at passing ratios are a third failure mode. A three hundred weight face at fourteen pixels on light gray may clear four point five to one. APCA’s weight input pushes the pair below threshold. WCAG has no weight dial below the large and bold exception. The reverse also happens, especially with dark mode and light text on dark surfaces. APCA’s polarity handling can approve certain white-on-near-black pairs for large display type that WCAG flags below four point five to one if misclassified as normal text. Large bold headlines are another zone. APCA explicitly allows lower Lc at thirty-two pixels and seven hundred weight. WCAG still demands three to one for large text, but large classification errors create WCAG failures where APCA considers the pair fine for display use.

Do not treat APCA passes as exemption from WCAG obligations on regulated projects. Treat them as signal that you should re-check classification, pixel size, and which standard your deliverable must cite. Dark mode is where signed Lc helps most. Polarity-aware review prevents shipping light-mode grays inverted without re-tuning. A fintech team once reused a dark primary text token name while applying a near-background hue on charcoal, yielding catastrophic contrast near one point two to one. After correction, secondary muted that scored five point eight to one WCAG landed at Lc seventy-two APCA at fourteen pixels, borderline for body. Darkening muted one step reached Lc seventy-eight and seven point one to one WCAG. The fix was token tuning, not a philosophical debate about which algorithm was more correct.

Andrew Somers publishes APCA research and the canonical calculator at Myndex. APCA constants have revision labels such as 0.98G. Figma plugins and npm packages sometimes lag. For audit trails, record tool name and APCA version, font family size and weight, foreground and background values in hex or OKLCH, and polarity. If two tools disagree, the Myndex reference implementation wins for dispute resolution until your contract specifies otherwise. The Silver Task Force is developing WCAG 3.0. Contrast may move from a single ratio to methods like APCA with size and weight tables. Public drafts change over years. Procurement clauses have not. Until WCAG 3 publishes and jurisdictions adopt it, WCAG 2.x contrast remains the enforceable default for most government and enterprise requests for proposal.

Case study: the muted caption incident

A B2B SaaS dashboard shipped with a design system specifying a muted text token for labels, timestamps, and helper copy. Tokens were built in OKLCH with even lightness steps. Visually pleasing in Figma, where artboards default to one hundred percent zoom and type renders larger than in production. Automated WCAG scans passed on pull requests. Designers celebrated a restrained hierarchy that felt premium against white cards and soft gray borders. Support had not yet seen the activity feed at scale.

Within three weeks, tickets clustered around unreadable dates in the activity feed. Users were not complaining about marketing headlines or primary navigation. They were struggling with twelve pixel muted timestamps on raised cards, exactly the pairs that looked elegant at design review scale. The primary text token still scored above twelve to one against the default surface. The muted token scored four point six to one against the same surface, a WCAG AA pass for normal text by the book. Against elevated card surfaces at slightly lower lightness, muted fell to four point one to one, a WCAG fail that the CI gate missed because tests ran only against the page background token, not against every surface variant components actually used.

An accessibility consultant reran the failing pairs through APCA with production metrics entered honestly: twelve pixels, four hundred weight, dark on light. Muted on default surface returned Lc sixty-eight. Muted on elevated card returned Lc sixty-one. Placeholder text on inputs returned Lc thirty-eight, acceptable only if you treat placeholders as non-content, which legal and product disagreed about for required fields. The spreadsheet made the pattern obvious. Token ramps optimized for aesthetics without size-specific APCA review passed automated WCAG while failing real readers on small UI chrome.

The fix was not bumping primary text contrast. Primary was never the problem. The team raised muted darkness from lightness 0.55 to 0.48 on white, darkening the gray rather than increasing chroma, and moved timestamps to thirteen pixels minimum in the activity feed component. WCAG marginally improved to five point one to one on surface. APCA reached Lc eighty-one at thirteen pixels. No brand accent colors changed. Card surfaces gained a documented secondary-muted alias one step darker for metadata on raised panels, so components stopped improvising opacity hacks that looked consistent in Figma and measured inconsistently in production.

Hero overlay work on the marketing site ran in parallel and taught an adjacent lesson. White headline copy over a full-bleed photograph with a CSS linear gradient scrim at thirty-five percent opacity passed WCAG when evaluated against the darkest scrim pixel at fifty-six pixels bold, classified as large text. User testing with low-vision participants surfaced uneven scrim coverage. Bright sky regions behind the top line yielded effective contrast near two point eight to one locally. WCAG evaluates text against adjacent background colors in the composite. Partial transparency makes the background ambiguous. The marketing fix strengthened scrim opacity and added text-shadow only as a secondary cue, not as the primary contrast strategy. Documented tests included worst-case spatial sampling and the flat-color fallback when images failed to load.

The dashboard incident changed process more than it changed hex values. The design system published minimum WCAG ratios per token pair and recommended APCA Lc bands per text style in the type scale. Future contributors knew why muted sat at lightness 0.48, not 0.55. CI contrast checks expanded to surface-raised and surface-sunk variants, not only the root background. Placeholder and disabled copy received explicit policy. If users must read it to complete tasks, it is not decoration under WCAG, regardless of what APCA assigns for non-content modes.

A dual-check workflow for production teams

Use WCAG for compliance gates and APCA for design-system tuning. Sequence matters because regulated work ends when WCAG fails, while product quality often begins where WCAG passes and APCA does not.

Define surfaces and text ramps in OKLCH with perceptual lightness steps before either formula runs. OKLCH reduces the chance that equal steps still cluster at failing ratios.

:root {
  --surface: oklch(0.98 0.01 260);
  --surface-raised: oklch(0.96 0.01 260);
  --text: oklch(0.22 0.02 260);
  --text-muted: oklch(0.45 0.02 260);
  --text-placeholder: oklch(0.62 0.02 260);
}

Run WCAG 2.2 AA on all text and essential UI. Test every semantic pair: primary, muted, links, buttons, badges, focus rings. Classify large text correctly. Fix failures before visual QA. Then run APCA on production metrics for each text style. Prioritize captions, placeholders, table metadata, and disabled-adjacent labels, the pairs WCAG approves at four point five to one but APCA flags.

Reconcile conflicts deliberately. If WCAG fails, darken or lighten until pass on regulated work. If WCAG passes but APCA fails, adjust muted tokens or increase size and weight before touching brand primaries. If APCA passes but WCAG fails, check dark-mode polarity, large-text classification, and whether the pair is decorative. Document both standards in the design system. Publish minimum WCAG ratios per token pair and recommended APCA Lc bands per text style. Do not mix standards in client reports. State plainly that you tested against WCAG 2.2 SC 1.4.3 and 1.4.11 with tool versions. If you also ran APCA, label it supplementary perceptual review, not a legal conformance claim.

Placeholders and disabled text remain contentious. If the label must be readable, treat it as text. If truly inactive, ensure state is communicated by more than color alone. WCAG contrast ratios are the law of the land for procurement, litigation risk, and automated continuous integration gates. APCA is the better tutor for why four point five to one feels wrong on twelve pixel muted captions over saturated cards. Run WCAG first, APCA second, fix tokens in OKLCH, and document what you tested. Stakeholders who passed QA should be able to read the caption without negotiating with their display.