Docs
Next

Colors

Use token color primitives with every Tailwind color utility, and theme-aware page backgrounds with bg-layout-*.

On this page

Every color primitive in your tokens is a Tailwind color, so bg-*, text-*, border-*, fill-* and the other color utilities accept it: bg-theme-600, text-base-1000, border-theme-200. Page and band backgrounds come from the color system as bg-layout-* classes, which follow the active theme.

Quick referenceLink to this section

The primitives, shown with bg-*. Every other color utility takes the same names (text-theme-600, border-base-200, ring-theme-500).

ClassStyles
bg-base-0background-color: var(--color-white);
bg-base-50background-color: var(--color-neutral-50);
bg-base-100background-color: var(--color-neutral-100);
bg-base-200background-color: var(--color-neutral-200);
bg-base-300background-color: var(--color-neutral-300);
bg-base-400background-color: var(--color-neutral-400);
bg-base-500background-color: var(--color-neutral-500);
bg-base-600background-color: var(--color-neutral-600);
bg-base-700background-color: var(--color-neutral-700);
bg-base-800background-color: var(--color-neutral-800);
bg-base-900background-color: var(--color-neutral-900);
bg-base-950background-color: var(--color-neutral-950);
bg-base-1000background-color: var(--color-black);
bg-theme-50background-color: var(--color-blue-50);
bg-theme-100background-color: var(--color-blue-100);
bg-theme-200background-color: var(--color-blue-200);
bg-theme-300background-color: var(--color-blue-300);
bg-theme-400background-color: var(--color-blue-400);
bg-theme-500background-color: var(--color-blue-500);
bg-theme-600background-color: var(--color-blue-600);
bg-theme-700background-color: var(--color-blue-700);
bg-theme-800background-color: var(--color-blue-800);
bg-theme-900background-color: var(--color-blue-900);
bg-theme-950background-color: var(--color-blue-950);

The layout backgrounds:

ClassStyles
bg-layout-mainbackground-color: var(--color-layout-bg-main);
bg-layout-alternativebackground-color: var(--color-layout-bg-alternative);

Basic usageLink to this section

PrimitivesLink to this section

With the default tokens there are two palettes: base, a neutral scale from 0 (white) to 1000 (black), and theme, the brand scale from 50 to 950.

Color primitives
base
0
50
100
200
300
400
500
600
700
800
900
950
1000
theme
50
100
200
300
400
500
600
700
800
900
950
const palettes = {
  base: [
    'bg-base-0',
    'bg-base-50',
    'bg-base-100',
    'bg-base-200',
    'bg-base-300',
    'bg-base-400',
    'bg-base-500',
    'bg-base-600',
    'bg-base-700',
    'bg-base-800',
    'bg-base-900',
    'bg-base-950',
    'bg-base-1000',
  ],
  theme: [
    'bg-theme-50',
    'bg-theme-100',
    'bg-theme-200',
    'bg-theme-300',
    'bg-theme-400',
    'bg-theme-500',
    'bg-theme-600',
    'bg-theme-700',
    'bg-theme-800',
    'bg-theme-900',
    'bg-theme-950',
  ],
}

export default function Demo() {
  return (
    <div className="flex w-full flex-col gap-6">
      {Object.entries(palettes).map(([name, swatches]) => (
        <div key={name} className="flex flex-col gap-2">
          <span className="font-mono text-xs font-semibold">{name}</span>
          <div className="grid grid-cols-7 gap-2 md:grid-cols-13">
            {swatches.map((swatch) => (
              <div key={swatch} className="flex flex-col gap-1">
                <div className={`h-10 rounded-md border border-black/10 ${swatch}`} />
                <span className="font-mono text-[10px]">{swatch.split('-').pop()}</span>
              </div>
            ))}
          </div>
        </div>
      ))}
    </div>
  )
}

Use primitives for one-off accents: a badge, an illustration, a highlight. They are the same in every theme, so for text and surfaces that should switch with the theme, use the color system roles below.

text-*, bg-* and border-* with primitives
NewDraftPublished
export default function Demo() {
  return (
    <div className="flex flex-wrap gap-3">
      <span className="bg-theme-50 text-theme-700 border-theme-200 rounded-full border px-3 py-1 text-sm font-medium">
        New
      </span>
      <span className="bg-base-100 text-base-700 border-base-300 rounded-full border px-3 py-1 text-sm font-medium">
        Draft
      </span>
      <span className="bg-theme-600 text-base-0 rounded-full px-3 py-1 text-sm font-medium">
        Published
      </span>
    </div>
  )
}

OpacityLink to this section

Add an opacity modifier to any color utility: bg-theme-500/20 mixes the color with transparency.

Opacity modifiers
/10
/25
/50
/75
/100
const steps = ['bg-theme-500/10', 'bg-theme-500/25', 'bg-theme-500/50', 'bg-theme-500/75', 'bg-theme-500']

export default function Demo() {
  return (
    <div className="grid w-full max-w-[480px] grid-cols-5 gap-2">
      {steps.map((step) => (
        <div key={step} className="flex flex-col gap-1">
          <div className={`h-12 rounded-md ${step}`} />
          <span className="font-mono text-[10px]">{step.replace('bg-theme-500', '') || '/100'}</span>
        </div>
      ))}
    </div>
  )
}

Layout backgroundsLink to this section

bg-layout-main and bg-layout-alternative set a band's background from the color system, so they switch with the theme. They are what the layoutBackground prop of Section and the other layout components renders. Switch the preview to the dark color system to see both change.

bg-layout-main and bg-layout-alternative
export default function Demo() {
  return (
    <div className="grid w-full grid-cols-2 overflow-hidden rounded-lg border border-(--color-foundations-surface-border)">
      <div className="bg-layout-main flex h-32 items-center justify-center">
        <span className="color-body font-mono text-sm">bg-layout-main</span>
      </div>
      <div className="bg-layout-alternative flex h-32 items-center justify-center">
        <span className="color-body font-mono text-sm">bg-layout-alternative</span>
      </div>
    </div>
  )
}

Color system rolesLink to this section

The other color system roles (foundations, links, components) have CSS variables but no classes of their own. Use them through Tailwind's variable shorthand: bg-(--color-foundations-surface-bg), text-(--color-foundations-text), border-(--color-foundations-surface-border). Every role and its variable is listed in Color tokens.

Responsive and state variantsLink to this section

Color utilities take every Tailwind variant: hover:bg-theme-700, focus-visible:ring-theme-500, md:bg-layout-alternative.

hover:bg-theme-700
export default function Demo() {
  return (
    <button
      type="button"
      className="bg-theme-600 text-base-0 hover:bg-theme-700 focus-visible:ring-theme-300 rounded-md px-4 py-2 text-sm font-medium transition-colors focus-visible:ring-4 focus-visible:outline-none"
    >
      Hover me
    </button>
  )
}

Theme switching does not need a variant. The color system roles (and bg-layout-*, color-heading, color-body, color-label) take their value from the nearest data-theme ancestor, so <section data-theme="dark"> recolors everything inside it. The theme-default and theme-dark classes do the same without the attribute; see Variable utilities. Tailwind's dark: variant follows the operating system's color scheme, not data-theme, unless you redefine it.

CustomizingLink to this section

The primitives come from the colorPrimitives collection and the roles from colorSystem, one mode per theme. Change them in Figma, generate a palette with Systhema Design, or override them in systhema.config:

systhema.config.ts
const config: SysthemaConfig = {
  customTokens: {
    colorPrimitives: {
      theme: { 500: '#7c3aed', 600: '#6d28d9' },
    },
    colorSystem: {
      default: { layout: { bg: { alternative: '#f5f3ff' } } },
    },
  },
}

A new palette key becomes a Tailwind color of the same name, and a new layout.bg key a bg-layout-<name> class. See Color tokens, Custom tokens and Themes and backgrounds. blocks.layout: false removes the bg-layout-* classes.