Skip to content
GitHub
Sections

Reference · Design Tokens

Contrast contract

This is a spec: descriptive guidance, not a checkable rule. It carries no forbidden and instead pair, and no jig check detector applies to it directly.

The spec

Floor: WCAG 2.1 AA. Two thresholds, and the boundary between them is a common mistake.

Threshold
Small text — 18px or less4.5:1
Large text — 24px+ regular, or 18px+ bold3:1
UI elements — input, checkbox and radio borders; meaningful icons3:1
Decorative elements that convey no meaningnone

Test against fill, not against the background. Text and controls can sit on a fill surface (a tag, a badge, a highlighted row), which is the lowest-contrast case. A colour that passes on the page background can fail inside a tag. In dark mode, test against bg-overlay — the brightest level, and therefore the worst case for a light-on-dark foreground.

The brand colour needs 4.5:1 against both bg-raised and fill, because it is used for link and button text.

When the brand colour cannot reach 4.5:1 — a yellow or very light brand, or a dark brand on a dark surface:

  1. 1.
    Darken or lighten it slightly, if brand recognition survives.
  2. 2.
    Use --color-text-strong for interactive elements instead, and keep the brand colour decorative.
  3. 3.
    Add a border to buttons so they clear 3:1.

APCA

WCAG 2's algorithm has known failures — it will pass black text on orange and fail white text on the same orange, when the white is plainly more readable, and it works poorly on dark interfaces. APCA (WCAG 3 draft) measures perceptually and scores by size and weight rather than a flat ratio.

Guidance: for commercial work, comply with WCAG 2.1 AA, because that is what is legally referenced. Check APCA as well, particularly on dark surfaces. Aim to pass both.

APCA reference values, with the sizes they apply at — a score means nothing without one, since APCA takes size and weight into account and thin or small text scores lower for the same colours:

ScoreApplies to
90Preferred for body text, 14px regular and above
75Minimum for body text, 18px regular and above
60Minimum for other text, 24px regular or 16px bold and above
45Minimum for large text — 36px regular or 24px bold and above — and for interface elements
30Absolute minimum for text: placeholders, disabled button text
15Minimum for non-text elements

These thresholds are APCA's own and do not line up with WCAG's large-text definition (C-17, 24px regular / 18.66px bold) — the two systems measure differently, and each is right inside its own frame.

Kind
Spec
Section
Design Tokens

Read as plain text