Theming

Build applications that support multiple color schemes. Learn design tokens, light/dark toggling, and multi-theme architecture with Tailwind CSS.

Design Tokens

Design tokens are the single source of truth for your visual language — colors, spacing, radii, and fonts. Instead of scattering hex codes everywhere, you define them once and reference them by name.

Token-Based Architecture
/* globals.css — Define your tokens */
@theme {
  --color-primary: #6366f1;
  --color-primary-hover: #4f46e5;
  --color-secondary: #ec4899;
  --color-background: #ffffff;
  --color-foreground: #0a0a0a;
  --color-muted: #737373;
  --color-border: #e5e5e5;

  --radius-sm: 0.375rem;
  --radius-md: 0.5rem;
  --radius-lg: 1rem;
}

/* Usage — semantic, readable, consistent */
<button className="bg-primary hover:bg-primary-hover
  text-white rounded-md px-4 py-2">
  Save Changes
</button>
Why Tokens? If your designer changes the brand color from indigo to blue, you update one variable instead of searching through hundreds of files for bg-indigo-500.

Light / Dark Toggle

The simplest theming pattern: two color schemes (light and dark) switched via a class on the root element. This app uses this exact approach.

Dark Mode with CSS Variables
/* globals.css */
:root {
  --color-background: #ffffff;
  --color-foreground: #0a0a0a;
  --color-card: #ffffff;
  --color-border: #e5e5e5;
}

.dark {
  --color-background: #0a0a0a;
  --color-foreground: #fafafa;
  --color-card: #171717;
  --color-border: #262626;
}

/* Your components stay the same! */
<div className="bg-[var(--color-card)]
  border-[var(--color-border)]
  text-[var(--color-foreground)]">
  Adapts automatically to theme
</div>
Live Demo — These cards respond to your current theme:

Light Mode

Clean, bright surfaces

Dark Mode

Easy on the eyes at night

Multi-Theme Architecture

Need more than just light/dark? Use data-theme attributes to support unlimited color schemes — perfect for SaaS apps that let users pick their own theme.

Multiple Themes with data-theme
/* globals.css */
:root,
[data-theme="default"] {
  --color-primary: #6366f1;  /* Indigo */
  --color-accent: #f59e0b;
}

[data-theme="ocean"] {
  --color-primary: #0ea5e9;  /* Sky blue */
  --color-accent: #06b6d4;
}

[data-theme="forest"] {
  --color-primary: #22c55e;  /* Green */
  --color-accent: #84cc16;
}

/* Toggle in React: */
<html data-theme="ocean">
  {/* Everything inside uses ocean colors */}
</html>

/* All your components remain unchanged! */
<button className="bg-primary text-white">
  I'm sky blue in ocean mode,
  indigo in default mode,
  and green in forest mode — automatically.
</button>
The Architecture: Your components never reference specific colors like bg-indigo-500. They only use semantic tokens like bg-primary. The CSS variables resolve the actual hex value based on which data-theme is active. This means zero component changes when adding a new theme.