theming

Tailwind CSS v4 introduces a CSS-first theming model. Design tokens live in your CSS file, not a JavaScript config. This makes customisation faster, more explicit, and aligned with the CSS custom properties ecosystem.

How Tailwind v4 theming works

In Tailwind v4, the @theme directive defines your design tokens as CSS custom properties. Tailwind reads these properties and automatically generates the corresponding utility classes. No JavaScript configuration is needed.

Tailwind v3 (old way)

// tailwind.config.js
module.exports = {
theme: {
  extend: {
    colors: {
      brand: '#6366F1',
    },
  },
},
}

Tailwind v4 (new way)

/* global.css */
@import "tailwindcss";

@theme {
--color-brand: #6366F1;
}

/* bg-brand, text-brand, etc.
 are now available! */

Customising your colour palette

Replace or extend the default Tailwind palette by defining colour tokens in the @theme block. Use any valid CSS colour format — hex, RGB, HSL, or the modern oklch() space for perceptually uniform colours.

styles/global.css
@import "tailwindcss";

@theme {
/* Override a default colour */
--color-indigo-500: #6366F1;

/* Add entirely new colours */
--color-brand-50:  oklch(97% 0.02 250);
--color-brand-500: oklch(60% 0.20 250);
--color-brand-900: oklch(30% 0.15 250);

/* Semantic colours */
--color-success: oklch(65% 0.18 145);
--color-danger:  oklch(60% 0.22  25);
}

indigo-50

indigo-100

indigo-200

indigo-400

indigo-500

indigo-600

indigo-700

indigo-900

Default indigo palette included with Tailwind v4.

Typography tokens

Override font families, sizes, weights, and line-heights using the same @theme approach.

/* styles/global.css */
@import "tailwindcss";

@theme {
  /* Font families */
  --font-sans: 'Inter', 'system-ui', sans-serif;
  --font-mono: 'JetBrains Mono', 'Fira Code', monospace;
  --font-display: 'Cal Sans', 'Inter', sans-serif;

  /* Custom font sizes */
  --text-2xs: 0.625rem;  /* 10px */
  --text-3xl: 1.875rem;  /* 30px */

  /* Line heights */
  --leading-tighter: 1.15;
}

After defining --font-sans, use it as font-sans in your Tailwind class names. The same applies to all other token categories.

Spacing and border-radius

@theme {
  /* Custom spacing scale additions */
  --spacing-18: 4.5rem;
  --spacing-22: 5.5rem;

  /* Border radii */
  --radius-sm:  0.25rem;
  --radius-md:  0.5rem;
  --radius-lg:  0.75rem;
  --radius-xl:  1rem;
  --radius-2xl: 1.5rem;
  --radius-full: 9999px;
}

Dark mode

Tailwind v4 supports dark mode via the dark: variant. Configure the strategy in your CSS:

@import "tailwindcss";

/* Use class-based dark mode (add 'dark' class to <html>) */
@variant dark (&:where(.dark, .dark *));

@layer base {
  :root {
    --bg-page: 255 255 255;
    --text-primary: 17 24 39;
  }

  .dark {
    --bg-page: 15 23 42;
    --text-primary: 248 250 252;
  }
}

/* Usage in components: */
/* <div class="bg-white dark:bg-slate-900 text-gray-900 dark:text-slate-100"> */

To toggle dark mode, add or remove the dark class on the <html> element. You can do this with a small React hook that reads from localStorage or the OS preference via window.matchMedia('(prefers-color-scheme: dark)').

CSS layers

Tailwind v4 uses native CSS @layer for cascade control. The three built-in layers are:

LayerPurposeExample
baseElement-level defaults and resetsh1 { @apply text-3xl }
componentsReusable class abstractions.btn { @apply px-4 py-2 }
utilitiesSingle-purpose helper classes.text-balance { text-wrap: balance }