Skip to content
ColorTokensKitby Penguin Design Ventures
Contents
Explanation

How accessible is it?

What the palette guarantees for contrast in every hue and mode, and what you still need to check.

Updated View as Markdown

Text you draw with the tokens passes WCAG AA on the page and card backgrounds, in both modes and every hue. Four things stay yours to check: text on the third background, control borders, meaning shown by hue alone, and Increase Contrast.

swift
let theme = Color.proOrange   // Lisbon

VStack(alignment: .leading, spacing: 4) {
    Text("Lisbon")
        .font(.headline)
        .foregroundStyle(theme.foregroundPrimary)
    Text("3 nights from October 12")
        .font(.subheadline)
        .foregroundStyle(theme.foregroundSecondary)
    Text("€480")
        .font(.subheadline)
        .foregroundStyle(theme.foregroundTertiary)   // _700 in light mode, _300 in dark
}
.padding()
.background(theme.backgroundPrimary)     // _50 in light mode, _1000 in dark
light mode
Lisbon3 nights from October 12€480

The faintest line, the price in light mode, measures 6.10:1. AA asks 4.5:1 for body text.

What's guaranteed#

The same ratio in every hue#

swift
Color.proOrange._100.contrastRatio(to: Color.proOrange._700)   // 5.53, Lisbon
Color.proPink._100.contrastRatio(to: Color.proPink._700)       // 5.53, Kyoto
Color.proSky._100.contrastRatio(to: Color.proSky._700)         // 5.53, Reykjavík

Every hue has the same lightness at each stop, so a pair of stops measures the same in all 36 hues and in your brand's family, and theming keeps your contrast. Gray has its own ladder: 8.73:1 for this pair.

Stops far enough apart#

light mode
9 stops12 stops14 stops

When you pick stops yourself, count the stops between text and background. 9 apart passes AA for large text and control borders, 12 for body text, and 14 passes AAA, in all 37 families and between them. The distance rule covers other uses.

On screens without Display P3#

These ratios are exact on Display P3 screens, which every iPhone since the iPhone 7 has. An sRGB-only screen, like many external monitors, clips the colors beyond sRGB and moves a few pairs slightly. The text tokens still pass AA, at 4.77:1 or more, and stops 12 apart still reach 4.5:1. Stops 9 apart can dip to 2.93:1, and white on _600 to 4.48:1 in mint, teal and turquoise.

What you still check#

Text on the tertiary background#

light mode
Lisbon€480

On backgroundTertiary, tertiary text falls under 4.5:1 in both modes, and secondary text does in dark mode. The lowest, 3.51:1, is enough only for large text, so use foregroundPrimary for body text there.

The app-wide gray tokens on Color pass there, at 5.24:1 or more. Inverted secondary and tertiary text fall short on invertedBackgroundTertiary too.

Borders of controls#

light mode
BeachCityFood

A border that shows where a control is, like these tags' edges, needs 3:1 under WCAG's non-text contrast rule. outlinePrimary reaches it on every background token, in every hue and both modes, at 3.08:1 or more, as in borders people need to see. outlineSecondary and outlineTertiary are faint on purpose, for dividers and card edges, which WCAG sets no minimum for.

APCA scores#

The ratios on this page are WCAG 2, the standard audits check. APCA, the candidate for WCAG 3, estimates luminance its own way, so its scores move up to Lc 1.2 between hues. contrastRatio(to:method:) measures both.

Meaning shown by hue alone#

#ad5a5a
Sold out, proRed._600
#44824b
Booked, proGreen._600
#857c56
Sold out, deuteranopia
#7a7149
Booked, deuteranopia

Two families at the same stop differ only in hue. The second row is the pair as someone with deuteranopia, a red-green color blindness, sees it at full severity, and in grayscale the two are identical. So give color a second cue, as WCAG's use of color rule asks: a label, an icon, or a difference in lightness. Using tokens in charts shows how for data.

Increase Contrast#

The tokens follow light and dark mode, not the Increase Contrast setting. High contrast modes moves text and borders two stops further from the background when it's on.

Sources#

See also