← Pixel Studio

Accessibility

APCA Contrast

WCAG 2.1 asks: is the luminance ratio above 4.5:1? APCA asks: can a human actually read this text at this size, weight, and polarity? The difference is not academic. It changes which color pairs pass and which fail. Explore pairs, build a token palette, export with contrast data baked in.

Pixel's Design Studio

APCA

Explore contrast pairs with APCA's perceptual model. Build a token system with every pair measured. Export as W3C Design Tokens or CSS custom properties.

Color pair

Headline — 24px

Body text at 16px. The paragraph is the unit of thought.

Small text at 12px — captions, metadata, footnotes.

APCA contrast

Lc +97.5dark on light
Lc 90 Preferred
Fluent reading. Columns of body text.
Lc 75 Min body
Floor for body text.
Lc 60 Content
Sub-headings, captions, labels.
Lc 45 Large
Headlines, display type.
Lc 30 Minimum
Spot text, placeholder.
Lc 15 Non-text
Dividers, decorative.

WCAG 2.x vs APCA

WCAG 2.x (legacy)

16.91:1
AA Normal (4.5:1)
AA Large (3:1)
AAA Normal (7:1)
One number. No weight sensitivity. No polarity.

APCA (perceptual)

Lc +97.5
body text
100w/44px200w/28px300w/19px400w/16px500w/15px

44px / 100

28px / 200

Perception

Spatial frequency — why size matters

Human vision filters high spatial frequencies. Small text is high-frequency. Low contrast + small size = invisible. WCAG cannot model this. APCA can.

Contrast
12pxfails
blur: 2.1px (simulated)
Contrast
16pxbody safe
blur: 1.3px (simulated)
Contrast
24pxbody safe
blur: 0.4px (simulated)
Contrast
48pxbody safe

The blur simulates spatial frequency filtering at distance. Small text disappears first — exactly what APCA predicts. Slide to see 12px vanish while 48px survives.

Polarity

Polarity test

WCAG returns the same ratio regardless of direction. APCA treats them differently — because human vision does.

As entered
Sample text
WCAG 16.91:1/Lc +97.5
Swapped
Sample text
WCAG 16.91:1/Lc -99.5
WCAG: 16.91:1 both ways. APCA differs by 1.9 Lc.

Font size / weight matrix

Every cell shows whether this size + weight combination is safe at the current Lc.

Size100200300400500600700800900
10px442819161514141618
12px442819161514141618
14px4428191615AaAa1618
16px442819AaAaAaAaAa18
18px442819AaAaAaAaAaAa
21px4428AaAaAaAaAaAaAa
24px4428AaAaAaAaAaAaAa
28px44AaAaAaAaAaAaAaAa
32px44AaAaAaAaAaAaAaAa
36px44AaAaAaAaAaAaAaAa
48pxAaAaAaAaAaAaAaAaAa
60pxAaAaAaAaAaAaAaAaAa
72pxAaAaAaAaAaAaAaAaAa
96pxAaAaAaAaAaAaAaAaAa
body safecontentlarge onlynumber = min size needed

Add to token system

Promote the current pair to your token palette.

Colors are accessibility decisions encoded as tokens. When the token carries its contrast data, the system enforces what the designer intended.

APCA from Myndex / WCAG 3 Visual Contrast group. SA98G algorithm. Educational use.

Why APCA Exists

WCAG 2.1 contrast ratios use a simple formula: relative luminance of the lighter color divided by the darker. It works symmetrically — #767676 on white and white on #767676 produce the same 4.54:1 ratio. Human vision does not work symmetrically. Dark text on a light background is easier to read than the reverse. WCAG ignores this.

APCA (Accessible Perceptual Contrast Algorithm) models what the visual cortex actually does. It accounts for polarity (dark-on-light vs. light-on-dark), spatial frequency (small text needs more contrast than large text), and font weight (bold text is more legible at lower contrast). The result is a single number — Lc (Lightness Contrast) — that maps directly to readability.

The practical consequence: some pairs that pass WCAG fail APCA. Some that fail WCAG pass APCA. If you have ever looked at a "passing" gray-on-white combination and thought "nobody can read that," APCA is the reason you were right.

Lc Thresholds

Lc 75+ — Body Text

The floor for readable paragraph text at 16px or smaller. Below this, sustained reading becomes effortful. Most users will not notice the effort — they will notice that they stopped reading.

Lc 60+ — Content Text

Subheadings, secondary content, descriptions. Text the user scans rather than reads continuously. Size typically 14–18px. Weight 400–500.

Lc 45+ — Large Text

Headlines, display type, hero sections. Text above 24px or bold above 18px. The eye processes large glyphs differently — spatial frequency is lower, less contrast is needed.

Lc 30+ — Non-Text

Icons, focus rings, active borders. Visual elements that communicate state but are not read as text. Below Lc 30, even non-text elements become unreliable for users with reduced contrast sensitivity.

Polarity Matters

Dark text on a light background produces a positive Lc value. Light text on dark produces negative Lc. The absolute values are not equivalent — Lc +60 is more readable than Lc -60 at the same size. For dark-mode interfaces, you need higher absolute Lc to match light-mode readability. This is biology, not preference.

From Pairs to System

The System tab lets you define tokens (text, surface, accent) and generates a contrast matrix — every text color against every surface. Export as W3C Design Tokens or CSS custom properties. The contrast data travels with the tokens, so the system enforces what the designer intended.