Accessible Color Token System for Product Teams

阅读时间 8 分钟更新于 2026-06-29
📘 本文内容为英文原文,提供最准确的技术信息。中文解读和实操指南正在完善中。你也可以使用页面顶部的翻译工具。

A color token system usually starts as a neat Figma page: primary, secondary, success, warning, danger, background, text. Then product work hits it. Someone adds dark mode. Marketing wants a campaign theme. The dashboard team needs chart colors. Support needs warning banners that pass WCAG. Suddenly the tidy palette becomes a pile of one-off hex codes.

[💬] The fix is not "more colors." The fix is better jobs for each color. Accessible color tokens should describe intent, state, and surface — not just hue. When the token name says what the color does, teams stop guessing and accessibility checks become part of the system instead of a last-minute audit.

This guide shows a practical token structure for product teams: small enough to maintain, detailed enough for real UI states, and flexible enough to survive light mode, dark mode, brand refreshes, and data visualization work.

基础原理

Start with three layers, not one flat palette

A production-ready system needs base tokens, semantic tokens, and component tokens. Base tokens are raw values such as blue-600 or gray-950. Semantic tokens explain intent: text-primary, surface-raised, border-danger, action-primary-bg. Component tokens are the final overrides for specific pieces: button-primary-bg, alert-warning-border, chart-series-03.

The mistake: letting designers or developers use base tokens directly in product screens. A page that uses blue-600 everywhere looks tidy until dark mode arrives. Then blue-600 may be too dim on a dark surface, too loud in a warning context, or unreadable as link text. Semantic tokens give you a safe middle layer.

A usable naming pattern

Use names that answer four questions: what object, what role, what state, what theme? For example: color.text.primary, color.text.muted, color.surface.page, color.surface.card, color.action.primary.bg, color.action.primary.text, color.action.primary.bg-hover, color.border.focus.

That reads longer than #2563eb, but it saves time later. A developer can choose color.action.primary.bg without asking which blue to use. A designer can update the light theme and dark theme values behind the token without touching every button.

Accessibility belongs in token pairs

Contrast is not a property of one color. It is a relationship. So document tokens in pairs: text-primary on surface-page, action-primary-text on action-primary-bg, danger-text on danger-bg-subtle. Store the expected WCAG level beside each pair. If a token pair cannot hit 4.5:1 for normal text, mark it for icons, borders, or large display text only.

Real product example: status colors

Status colors break systems because teams use green, yellow, and red as if hue alone carries meaning. It does not. For accessible status design, create tokens for background, border, text, and icon. Add words or icons in the UI so color is never the only signal.

Success might use a soft green background, darker green text, and a check icon. Warning might use amber background, brown text, and a triangle icon. Error might use red background, red-brown text, and direct copy. The color helps, but the text and icon carry the meaning.

Chart colors need a separate lane

Do not reuse brand colors as chart series tokens. Charts need sequence, distinction, and color-blind safety. A good chart set includes at least eight series colors, plus hover and selected states. Test them in grayscale. If two adjacent lines collapse into the same gray value, the palette is not ready.

Dark mode is not inversion

A light theme blue can become electric on dark backgrounds. Reduce saturation slightly, raise lightness where needed, and test focus states separately. In dark mode, borders often need more opacity than they need in light mode because low-contrast edges disappear against dark surfaces.

Governance that people will actually follow

Keep a short token request path. If a team needs a new color, ask for the use case, surface, text size, and state. If an existing token works, point them to it. If it does not, add a semantic token and document the pair. Avoid approving raw hex values in product code unless it is an experiment with an expiry date.

真实案例

Start with three layers, not one flat palette

A production-ready system needs base tokens, semantic tokens, and component tokens. Base tokens are raw values such as blue-600 or gray-950. Semantic tokens explain intent: text-primary, surface-raised, border-danger, action-primary-bg. Component tokens are the final overrides for specific pieces: button-primary-bg, alert-warning-border, chart-series-03.

The mistake: letting designers or developers use base tokens directly in product screens. A page that uses blue-600 everywhere looks tidy until dark mode arrives. Then blue-600 may be too dim on a dark surface, too loud in a warning context, or unreadable as link text. Semantic tokens give you a safe middle layer.

A usable naming pattern

Use names that answer four questions: what object, what role, what state, what theme? For example: color.text.primary, color.text.muted, color.surface.page, color.surface.card, color.action.primary.bg, color.action.primary.text, color.action.primary.bg-hover, color.border.focus.

That reads longer than #2563eb, but it saves time later. A developer can choose color.action.primary.bg without asking which blue to use. A designer can update the light theme and dark theme values behind the token without touching every button.

Accessibility belongs in token pairs

Contrast is not a property of one color. It is a relationship. So document tokens in pairs: text-primary on surface-page, action-primary-text on action-primary-bg, danger-text on danger-bg-subtle. Store the expected WCAG level beside each pair. If a token pair cannot hit 4.5:1 for normal text, mark it for icons, borders, or large display text only.

Real product example: status colors

Status colors break systems because teams use green, yellow, and red as if hue alone carries meaning. It does not. For accessible status design, create tokens for background, border, text, and icon. Add words or icons in the UI so color is never the only signal.

Success might use a soft green background, darker green text, and a check icon. Warning might use amber background, brown text, and a triangle icon. Error might use red background, red-brown text, and direct copy. The color helps, but the text and icon carry the meaning.

Chart colors need a separate lane

Do not reuse brand colors as chart series tokens. Charts need sequence, distinction, and color-blind safety. A good chart set includes at least eight series colors, plus hover and selected states. Test them in grayscale. If two adjacent lines collapse into the same gray value, the palette is not ready.

Dark mode is not inversion

A light theme blue can become electric on dark backgrounds. Reduce saturation slightly, raise lightness where needed, and test focus states separately. In dark mode, borders often need more opacity than they need in light mode because low-contrast edges disappear against dark surfaces.

Governance that people will actually follow

Keep a short token request path. If a team needs a new color, ask for the use case, surface, text size, and state. If an existing token works, point them to it. If it does not, add a semantic token and document the pair. Avoid approving raw hex values in product code unless it is an experiment with an expiry date.

Accessible color tokens with contrast notes

:root {
  /* base tokens */
  --blue-600: #2563eb;
  --blue-700: #1d4ed8;
  --slate-50: #f8fafc;
  --slate-900: #0f172a;
  --red-50: #fef2f2;
  --red-700: #b91c1c;

  /* semantic tokens */
  --color-surface-page: var(--slate-50);
  --color-surface-card: #ffffff;
  --color-text-primary: var(--slate-900);
  --color-text-muted: #475569;

  /* action pair: white text on blue bg, AA for normal text */
  --color-action-primary-bg: var(--blue-600);
  --color-action-primary-bg-hover: var(--blue-700);
  --color-action-primary-text: #ffffff;

  /* status pair: danger text on subtle danger bg */
  --color-danger-bg-subtle: var(--red-50);
  --color-danger-text: var(--red-700);
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-surface-page: #020617;
    --color-surface-card: #0f172a;
    --color-text-primary: #e5e7eb;
    --color-text-muted: #94a3b8;
    --color-action-primary-bg: #60a5fa;
    --color-action-primary-bg-hover: #93c5fd;
    --color-action-primary-text: #082f49;
    --color-danger-bg-subtle: #450a0a;
    --color-danger-text: #fecaca;
  }
}

复制粘贴到项目即可使用。

测试方法

Start with three layers, not one flat palette

A production-ready system needs base tokens, semantic tokens, and component tokens. Base tokens are raw values such as blue-600 or gray-950. Semantic tokens explain intent: text-primary, surface-raised, border-danger, action-primary-bg. Component tokens are the final overrides for specific pieces: button-primary-bg, alert-warning-border, chart-series-03.

The mistake: letting designers or developers use base tokens directly in product screens. A page that uses blue-600 everywhere looks tidy until dark mode arrives. Then blue-600 may be too dim on a dark surface, too loud in a warning context, or unreadable as link text. Semantic tokens give you a safe middle layer.

A usable naming pattern

Use names that answer four questions: what object, what role, what state, what theme? For example: color.text.primary, color.text.muted, color.surface.page, color.surface.card, color.action.primary.bg, color.action.primary.text, color.action.primary.bg-hover, color.border.focus.

That reads longer than #2563eb, but it saves time later. A developer can choose color.action.primary.bg without asking which blue to use. A designer can update the light theme and dark theme values behind the token without touching every button.

Accessibility belongs in token pairs

Contrast is not a property of one color. It is a relationship. So document tokens in pairs: text-primary on surface-page, action-primary-text on action-primary-bg, danger-text on danger-bg-subtle. Store the expected WCAG level beside each pair. If a token pair cannot hit 4.5:1 for normal text, mark it for icons, borders, or large display text only.

Real product example: status colors

Status colors break systems because teams use green, yellow, and red as if hue alone carries meaning. It does not. For accessible status design, create tokens for background, border, text, and icon. Add words or icons in the UI so color is never the only signal.

Success might use a soft green background, darker green text, and a check icon. Warning might use amber background, brown text, and a triangle icon. Error might use red background, red-brown text, and direct copy. The color helps, but the text and icon carry the meaning.

Chart colors need a separate lane

Do not reuse brand colors as chart series tokens. Charts need sequence, distinction, and color-blind safety. A good chart set includes at least eight series colors, plus hover and selected states. Test them in grayscale. If two adjacent lines collapse into the same gray value, the palette is not ready.

Dark mode is not inversion

A light theme blue can become electric on dark backgrounds. Reduce saturation slightly, raise lightness where needed, and test focus states separately. In dark mode, borders often need more opacity than they need in light mode because low-contrast edges disappear against dark surfaces.

Governance that people will actually follow

Keep a short token request path. If a team needs a new color, ask for the use case, surface, text size, and state. If an existing token works, point them to it. If it does not, add a semantic token and document the pair. Avoid approving raw hex values in product code unless it is an experiment with an expiry date.

💡 高手技巧

工具推荐

Start with three layers, not one flat palette

A production-ready system needs base tokens, semantic tokens, and component tokens. Base tokens are raw values such as blue-600 or gray-950. Semantic tokens explain intent: text-primary, surface-raised, border-danger, action-primary-bg. Component tokens are the final overrides for specific pieces: button-primary-bg, alert-warning-border, chart-series-03.

The mistake: letting designers or developers use base tokens directly in product screens. A page that uses blue-600 everywhere looks tidy until dark mode arrives. Then blue-600 may be too dim on a dark surface, too loud in a warning context, or unreadable as link text. Semantic tokens give you a safe middle layer.

A usable naming pattern

Use names that answer four questions: what object, what role, what state, what theme? For example: color.text.primary, color.text.muted, color.surface.page, color.surface.card, color.action.primary.bg, color.action.primary.text, color.action.primary.bg-hover, color.border.focus.

That reads longer than #2563eb, but it saves time later. A developer can choose color.action.primary.bg without asking which blue to use. A designer can update the light theme and dark theme values behind the token without touching every button.

Accessibility belongs in token pairs

Contrast is not a property of one color. It is a relationship. So document tokens in pairs: text-primary on surface-page, action-primary-text on action-primary-bg, danger-text on danger-bg-subtle. Store the expected WCAG level beside each pair. If a token pair cannot hit 4.5:1 for normal text, mark it for icons, borders, or large display text only.

Real product example: status colors

Status colors break systems because teams use green, yellow, and red as if hue alone carries meaning. It does not. For accessible status design, create tokens for background, border, text, and icon. Add words or icons in the UI so color is never the only signal.

Success might use a soft green background, darker green text, and a check icon. Warning might use amber background, brown text, and a triangle icon. Error might use red background, red-brown text, and direct copy. The color helps, but the text and icon carry the meaning.

Chart colors need a separate lane

Do not reuse brand colors as chart series tokens. Charts need sequence, distinction, and color-blind safety. A good chart set includes at least eight series colors, plus hover and selected states. Test them in grayscale. If two adjacent lines collapse into the same gray value, the palette is not ready.

Dark mode is not inversion

A light theme blue can become electric on dark backgrounds. Reduce saturation slightly, raise lightness where needed, and test focus states separately. In dark mode, borders often need more opacity than they need in light mode because low-contrast edges disappear against dark surfaces.

Governance that people will actually follow

Keep a short token request path. If a team needs a new color, ask for the use case, surface, text size, and state. If an existing token works, point them to it. If it does not, add a semantic token and document the pair. Avoid approving raw hex values in product code unless it is an experiment with an expiry date.

免费工具推荐

用这些免费工具实操你学到的知识: