Skip to main content
ColorRow
Colorrow Guide

Semantic Color Tokens for Maintainable UI Themes

Raw color scales describe what colors exist. Semantic tokens describe what those colors mean in the interface. Keeping those layers separate makes components easier to theme, rebrand, audit, and maintain.

Published August 15, 2026Updated September 26, 20264 min readPractical guide
ColorRow

Published by ColorRow. Practical guidance with examples and links to the tools. About our editorial process

WORKED EXAMPLE

Separate a decorative accent from an error

#202A44#5260E8#BAC7ED#F0D9CA#FAFAF7

Suppose a brand uses a warm peach accent. Calling both a promotional badge and a form error --accent makes a future rebrand risky: changing a decorative color would also change an important status.

--color-accent: #f0d9ca;
--color-error-ink: #9c2424;
--color-error-surface: #fff0ef;

The error component should consume the error roles and include a written explanation. The promotional badge should consume the accent role. Test error text on the error surface and on any surrounding page surface where the message can appear.

Try this palette in Generator ↗

Raw colors and semantic colors answer different questions

A raw palette might contain blue-500, gray-50, and red-600. Those names describe a color family or scale position. A semantic layer contains names such as color-background, color-text, color-primary, and color-danger. Those names describe purpose.

:root {
  --blue-600: #2563eb;
  --slate-50: #f8fafc;
  --slate-950: #020617;

  --color-background: var(--slate-50);
  --color-text: var(--slate-950);
  --color-primary: var(--blue-600);
}

Components should usually consume the semantic layer. A button that references --color-primary can survive a rebrand or theme change without knowing which raw shade currently supplies that role.

Start with a small role vocabulary

Do not create hundreds of semantic tokens before the product has those needs. A compact system can begin with background, surface, primary, secondary, accent, text, muted text, and border. Add success, warning, danger, focus, selected, and disabled roles when the component system requires them.

RoleTypical jobReview question
BackgroundPage canvasDo text, focus, and surface boundaries remain visible?
SurfaceCards, panels, menusIs elevation clear without depending only on a tiny color difference?
PrimaryMain interactive emphasisDo text/icon combinations pass in every state?
Text / mutedContent hierarchyIs muted text still readable at its actual size?
BorderSeparation and control boundariesIs the boundary visible where it carries functional meaning?

Theme by remapping roles

Light and dark themes work best when components keep their semantic references and the theme changes which raw values fill those roles. This avoids component-specific inversion logic and makes theme review systematic.

[data-theme="dark"] {
  --color-background: var(--slate-950);
  --color-surface: var(--slate-900);
  --color-text: var(--slate-50);
  --color-primary: var(--blue-400);
}

Tokens do not guarantee accessibility

Semantic naming improves consistency, but it does not make a color pairing accessible by itself. The same primary token may be safe as a large filled button and unsafe as small text on a white background. Document which role combinations are permitted and test component states, not just token values.

Keep export formats secondary to the model

CSS variables, JSON, SCSS, and JavaScript objects are transport formats. The important part is the stable semantic model behind them. If every platform uses the same role names and meanings, teams can generate platform-specific files without losing the design intent.

Colorrow workflow Use the Design Token Generator to assign palette colors to semantic roles and export CSS, JSON, SCSS, or JavaScript. Then use the Palette Visualizer to inspect those roles in several interface patterns.

A maintainable token review

  1. List the raw palette independently from semantic roles.
  2. Assign the smallest useful role set.
  3. Define component-level tokens only when a component truly needs independent control.
  4. Map light and dark themes through the same semantic vocabulary.
  5. Audit allowed contrast pairings and focus/status states.
  6. Export to code only after the naming and role model are stable.

Practical checklist

  • Keep raw palette names separate from semantic role names
  • Use a small stable role vocabulary first
  • Map themes through roles rather than component-specific inversions
  • Test permitted role pairings and component states
  • Export code only after the semantic model is stable

Sources and standards

CSS custom-property syntax in the examples was checked against the W3C specification.

Editorial note

Published and reviewed by the ColorRow on August 15, 2026. Suggestions and corrections can be sent to contact.colorrow@gmail.com.