Color Systems
color systems color systems structure palettes into primitives (hue ramps), semantic roles (text, surface, border, interactive), and state layers (hover,
Introduction
Color systems structure palettes into primitives (hue ramps), semantic roles (text, surface, border, interactive), and state layers (hover, disabled, focus). Staff engineers implement with OKLCH/LCH for perceptual uniformity — fixing "same hex, different perceived brightness" across hues when building accessible dark themes.
Material dynamic color, Carbon themes, and Atlassian color tokens demonstrate semantic-first color architecture.
Business problem
Business pressure: Brand palette has 12 blues used inconsistently; dark mode grays look muddy. Color system enforces ramps and semantic mapping — accessibility audits pass because contrast is computed at token definition time.
- WCAG: Documented contrast pairs in token metadata.
- Dark mode: Semantic remap, not inverted hex.
- Data viz: Categorical palette distinct from UI chrome colors.
Why this feature exists
Platform history: HSL ramps in Bootstrap; Material Design color tooling; OKLCH in modern CSS enables perceptual ramps in token generators.
- Problem solved: One-off colors and failed contrast in dark theme.
- Modern role: OKLCH in tokens + color-mix() for states.
Browser rendering perspective
Rendering impact: Colors are cheap to paint. Gradients and wide-gamut P3 colors can trigger different compositor paths — test on Safari.
Internal browser workflow
Flow: Define ramps → semantic map per theme → components use semantic only → states via color-mix or dedicated state tokens.
Feature deep dive
Semantic color roles:
:root {--color-blue-500: oklch(58% 0.2 264);--color-surface: oklch(100% 0 0);--color-text-primary: oklch(25% 0.02 264);--color-border-subtle: color-mix(in oklch, var(--color-text-primary) 15%, transparent);--color-interactive: var(--color-blue-500);--color-interactive-hover: color-mix(in oklch, var(--color-interactive) 85%, black);}
Syntax
Carbon: $interactive-01, $text-01. Polaris: color tokens in TS. Material: on-surface, primary-container.
Examples
Contrast check in token CI:
// apca or wcag contrast between token pairs in build scriptassertContrast('--color-text-primary', '--color-surface', 4.5);
Real-world use
Material 3 color roles and dynamic color from wallpaper. Carbon g10/g90 gray ramps. Atlassian legacy blue to new semantic palette migration. Shopify Polaris green brand system.
Real production example
Pattern: stylelint-color-format oklch; CI contrast matrix for all semantic pairs per theme.
Enterprise use case
Enterprise: Carbon theme files remap entire semantic set. Atlassian token package documents forbidden primitive usage in apps.
Accessibility considerations
A11y: Never convey state by color alone — pair with icon, weight, or pattern. Focus ring token separate from brand color.
Performance considerations
Performance: color-mix() computed at style time — negligible vs layout.
SEO considerations
SEO: Low contrast body text hurts readability scores in Lighthouse accessibility audit indirectly.
Scalability considerations
Scale: Data visualization palette separate token file — 12 categorical colors audited for distinction.
Common production issues
Failures: #000 on #121212 in "dark mode" — not true dark semantic surfaces.
Debugging guide
Debug: DevTools color picker shows computed oklch; accessibility panel contrast ratio.
Best practices
- OKLCH ramps for generation; semantic for consumption.
- CI contrast checks on token pairs.
- Separate data viz palette.
Anti-patterns
- opacity on text for secondary — contrast fails on non-white bg.
- Gray text #999 on white without audit.
Trade-offs
- OKLCH: perceptual; older browser fallback needed.
- Hex legacy: familiar; bad for dark mode ramps.
Architecture review questions
- All semantic pairs pass contrast in both themes?
- Primitive color usage banned in apps?
Interview questions
Why OKLCH for design tokens?(Advanced)
Perceptually uniform lightness — interpolating L produces even steps unlike HSL where yellow and blue at same L look different brightness. Better dark mode ramp generation.
Follow-up: Material dynamic color approach?
Hands-on exercise
Exercise: Build 5-step OKLCH ramp; map to semantic roles; verify WCAG pairs in script.
Staff engineer notes
- Color system = semantic roles + contrast CI — not a Figma swatch page.
Common pitfalls
- Using brand primary for error red — semantic confusion.
Try it yourself
Edit the CSS panel — the preview updates live. Use DevTools Performance and Accessibility panels to validate.
Try it yourself
Summary
Color systems structure palettes into semantic roles with perceptual ramps and audited contrast — following Material, Carbon, Atlassian, and Polaris patterns.
Key takeaways
- Primitives → semantic roles → components.
- OKLCH and CI contrast for accessible themes.