color theory

On-Color

On-color is the token convention that attaches a pre-tested foreground color to every background role in your palette. Material Design 3 made it mainstream in 2021 with tokens like on-primary, on-surface, on-error, and on-secondary-container. Pick the background role and the matching on-color delivers at least 4.5:1 contrast by design. The contract lives in the token file, not in last-minute Figma critiques or audit scrambles. This is the exact token-layer fix the accessible color contrast article demands. Designers stop choosing between brand punch and compliance because the system already solved the math. The vivid purple stays vivid. The text on top stays readable. Everybody ships faster.

On-color is not generic white text on a colored button. It is not an after-the-fact hack you apply when an auditor complains. It is not the reason interfaces turn into gray mush. That disaster comes from teams who desaturate every hue instead of fixing pairings. It is not WCAG theater or a perceptual replacement for APCA. It works alongside both. It is not optional for functional UI. Borders, icons with meaning, focus rings, and form fields all fall under the 3:1 non-text rule. Skip the on-color discipline there and you fail audits regardless of how clean your body copy looks.

A concrete example sits in Material Design 3 from the 2021 Material You launch. Feed the system a wallpaper color and it spits out a full palette where on-primary is locked to deliver 6.2:1 against primary every single time. A deep indigo primary gets white text. A pale yellow primary switches to near-black on-primary so the ratio holds. Google rolled this into Gmail, Maps, and Drive. No more contrast tickets from users on cheap monitors or in direct sunlight. Radix Colors copied the spirit in 2022 with step 12 text guaranteed against step 1 and 2 backgrounds. Shopify Polaris added explicit on-action tokens in their 2023 refresh after years of dark-mode failures in their admin panels. Stripe updated their primitives in early 2024 to include on-accent roles for their red brand after an audit caught low-contrast CTAs. Each team kept their distinct visual identity while killing an entire category of bugs. The article shows the same principle in GitHub Primer where published ratios sit next to every fg and bg token so the on-color choice is never a guess.

Use on-color when you are scaling a design system across products, themes, or large teams. Drop it into token definitions early so Storybook, CI checks with axe-core, Figma handoff plugins, and production Lighthouse scans all inherit the safety. It pays off hardest in SaaS tools like Linear, Vercel, and Notion where dark mode flips and brand accents must survive constant iteration. Pair it with OKLCH scales and APCA targets and you exceed WCAG 2.2 legally while beating real-world readability benchmarks. Deploy it for buttons, form fields, navigation, and any element that carries meaning. The pattern removes contrast from critique entirely so you argue about hierarchy and motion instead.

Skip on-color during raw brand exploration or marketing landing pages where you are deliberately breaking rules for impact. Hero headlines at 2.8:1 can create drama that strict tokens would kill. Avoid it on logotypes, decorative illustrations, or data visualizations where color carries separate semantic weight. Do not adopt the names if your team still works in raw hex values instead of tokens because the benefit evaporates without the system layer enforcing them. Never treat on-color as a substitute for testing with actual low-vision users. Tokens get you 80 percent there. Real humans reveal the rest.

On-color turns accessibility from a recurring fight into a default setting so you can focus on making interfaces that do not suck.

Related terms

Keep exploring