Skip to content

Tailwind CSS v4

The tailwind() builder renders Tailwind CSS v4 @theme blocks. Map token types to Tailwind namespaces, add custom variants, and optionally include the Tailwind import.

import { tailwind } from 'dispersa'
OptionTypeDefaultDescription
namestringUnique output identifier
filestring or functionOutput path (supports {*context*} interpolation for modifiers)
preset’bundle’ | ‘standalone''bundle’Output preset
includeImportbooleantrueAdd @import "tailwindcss"
namespacestringTheme namespace for @theme namespace(...)
selectorstring or SelectorFunctionCSS selector for theme variants
mediaQuerystring or MediaQueryFunctionMedia query wrapper
minifybooleanfalseMinify output
transformsTransform[]Per-output transforms
filtersFilter[]Per-output filters
import { Dispersa, tailwind } from 'dispersa'
import { nameKebabCase, colorToHex, dimensionToPx } from 'dispersa/transforms'
const dispersa = new Dispersa({
resolver: './tokens.resolver.json',
buildPath: './dist',
})
await dispersa.build({
outputs: [
tailwind({
name: 'theme',
file: 'theme.css',
transforms: [nameKebabCase(), colorToHex(), dimensionToPx()],
}),
],
})

Output:

@theme {
--color-brand-primary: #0066cc;
--spacing-medium: 16px;
}

The namespace option sets the Tailwind v4 @theme namespace(...) directive, scoping all generated variables under a prefix:

tailwind({
name: 'theme',
file: 'theme.css',
namespace: 'ds',
transforms: [nameKebabCase(), colorToHex()],
})

Output:

@theme namespace(ds) {
--color-brand-primary: #0066cc;
--spacing-medium: 16px;
}

Token types are automatically mapped to Tailwind-compatible CSS variable prefixes internally (e.g., color tokens get --color-*, dimension tokens get --spacing-*).

With the bundle preset, modifier overrides use @custom-variant for theme switching:

tailwind({
name: 'themed',
file: 'theme.css',
preset: 'bundle',
includeImport: true,
transforms: [nameKebabCase(), colorToHex()],
})

Use selector functions to target [data-theme] or similar for theme variants:

tailwind({
name: 'themed',
file: 'theme.css',
preset: 'bundle',
selector: (modifierName, context, isBase, allModifierInputs) => {
if (isBase) return ':root'
return `[data-${modifierName}="${context}"]`
},
transforms: [nameKebabCase(), colorToHex()],
})