Theme & Customization
Tailwind's theme is a flat set of CSS variables. You extend or replace it with a @theme { … } block in your input CSS, reference those values from inside CSS via the theme functions, and read the resolved values back from PHP. There is no JavaScript config file — the theme lives entirely in CSS.
The @theme block
A @theme block declares design tokens as CSS custom properties. The namespace prefix on each variable (--color-*, --font-*, --breakpoint-*, --spacing-*, …) tells Tailwind which utilities and variants the token feeds.
use TailwindPHP\tw;
$css = tw::generate('<div class="bg-brand text-brand xs:flex">', '
@import "tailwindcss";
@theme {
--color-brand: #3b82f6;
--font-heading: "Inter", sans-serif;
--breakpoint-xs: 20rem;
--spacing-huge: 10rem;
}
');Each token registers utilities under its namespace. The example above makes bg-brand, text-brand, border-brand, the font-heading family, an xs: responsive variant, and p-huge/m-huge spacing available — generated only when the class appears in your content.
/* bg-brand resolves to the theme variable */
:root {
--color-brand: #3b82f6;
}
.bg-brand {
background-color: var(--color-brand);
}The --breakpoint-xs token registers the xs: variant directly:
@media (min-width: 20rem) {
.xs\:flex {
display: flex;
}
}Common namespaces
| Namespace | Feeds |
|---|---|
--color-* | bg-*, text-*, border-*, fill-*, stroke-*, … |
--font-* | font-* family utilities |
--text-* | text-* font-size utilities |
--breakpoint-* | responsive variants (sm:, md:, custom xs:) |
--spacing-* | named spacing values (p-huge, m-huge) |
--radius-* | rounded-* utilities |
--shadow-* | shadow-* utilities |
Clearing a namespace
Setting a namespace wildcard to initial removes Tailwind's defaults for that namespace before your own tokens are added. This lets you start from a clean palette:
@theme {
/* Drop every default color, then define only what you need */
--color-*: initial;
--color-brand: #3b82f6;
--color-ink: #111827;
}--*: initial; clears the entire theme. A single value of initial on a non-wildcard key (--color-red-500: initial;) removes just that one token. Only initial is accepted as the value for a -* wildcard — any other value is an error.
Reading theme values in CSS
theme()
The legacy theme() function reads a value using dot notation against the v3-style namespaces. It resolves to the token's value at compile time, so it can be used anywhere a value is expected — including custom rules and other declarations.
$css = tw::generate('<div class="callout">', '
@import "tailwindcss";
.callout { color: theme(colors.red.500); }
');.callout {
color: oklch(63.7% .237 25.331);
}Dot paths map to the underlying variables (colors.red.500 → --color-red-500, fontFamily.sans → the sans family). An opacity modifier is supported: theme(colors.red.500 / 50%). A fallback can be passed as a second argument: theme(colors.brand, #000). If a path cannot be resolved and no fallback is given, the candidate using it is dropped.
--theme()
--theme() reads a theme variable by its CSS custom-property name and returns a var() reference by default, so the value stays overridable at runtime:
.btn { color: --theme(--color-brand); }
/* → color: var(--color-brand); */Add inline to substitute the resolved value instead of a var() reference: --theme(--color-brand inline). A second argument is a fallback (--theme(--color-brand, #000)), and an initial fallback is handled specially — it is injected into nested var() references that themselves resolve to initial. Inside an at-rule (@media, @container), --theme() always resolves inline because var() is not valid in those preludes.
--spacing()
--spacing(n) multiplies the theme's base spacing unit (--spacing) by n:
@utility my-gap { gap: --spacing(4); }
/* → gap: calc(var(--spacing) * 4); */This is the same calculation the built-in spacing utilities use, so custom values stay consistent with p-4, m-4, and friends.
--alpha()
--alpha(color / opacity) applies an opacity to a color using a color-mix() in the oklab color space:
@utility tint { color: --alpha(var(--color-red-500) / 50%); }
/* → color: color-mix(in oklab, var(--color-red-500) 50%, transparent); */Stacking opacity and color-mix() → oklab()
Opacity modifiers compose. Applying 50% on a value that already carries 50% yields 25%, computed in oklab. When an opacity modifier resolves against a static color, TailwindPHP folds the color-mix(in oklab, …) expression down to a concrete oklab() value — the same conversion lightningcss performs in the upstream Tailwind toolchain — while dynamic colors (those still wrapped in var()) keep the color-mix() form so they remain runtime-overridable.
Reading theme values from PHP
Three accessors return resolved theme values as PHP arrays. They accept the same input formats as tw::generate() and are also available on a compiler instance.
use TailwindPHP\tw;
tw::colors();
// ['red-500' => 'oklch(63.7% .237 25.331)', 'blue-500' => 'oklch(62.3% .214 259.815)', ...]
tw::breakpoints();
// ['sm' => '40rem', 'md' => '48rem', 'lg' => '64rem', 'xl' => '80rem', '2xl' => '96rem']
tw::spacing('@import "tailwindcss"; @theme { --spacing-huge: 10rem; }');
// ['huge' => '10rem']Pass a CSS string to read against a customized theme:
tw::colors('@import "tailwindcss"; @theme { --color-brand: #3b82f6; }');
// [..., 'brand' => '#3b82f6']
tw::breakpoints('@import "tailwindcss"; @theme { --breakpoint-xs: 20rem; }');
// ['xs' => '20rem', 'sm' => '40rem', ...]TailwindCSS 4 uses a single --spacing base value rather than a --spacing-* scale, so tw::spacing() returns only the custom --spacing-* tokens you define. From a compiler instance the same methods exist: $compiler->colors(), $compiler->breakpoints(), $compiler->spacing(). See the API for full signatures.
Next steps
- Directives —
@apply,@utility,@custom-variant,@layer. - Imports —
@import, virtual modules, and Preflight. - API — every accessor and inspection method.
Overview
Generate Tailwind CSS from your content — scan markup for class names, pass optional CSS configuration, and get back only the CSS you use.
Directives
Inline utilities with @apply, register custom utilities with @utility, define variants with @custom-variant, and control cascade order with @layer.