Skip to content

CSS

The css() builder renders design tokens as CSS custom properties (variables). You control selectors, media queries, and theming with flexible options.

import { css } from 'dispersa'
OptionTypeDefaultDescription
namestringUnique output identifier
filestring or functionOutput path (supports {*context*} interpolation for modifiers)
preset’bundle’ | ‘standalone’ | ‘modifier''bundle’Output preset
selectorstring or SelectorFunction':root'CSS selector
mediaQuerystring or MediaQueryFunctionMedia query wrapper
preserveReferencesbooleanfalseEmit var() for aliases
minifybooleanfalseMinify output
transformsTransform[]Per-output transforms
filtersFilter[]Per-output filters
import { Dispersa, css } from 'dispersa'
import { nameKebabCase, colorToHex, dimensionToPx } from 'dispersa/transforms'
const dispersa = new Dispersa({
resolver: './tokens.resolver.json',
buildPath: './dist',
})
await dispersa.build({
outputs: [
css({
name: 'tokens',
file: 'tokens.css',
preset: 'bundle',
selector: ':root',
transforms: [nameKebabCase(), colorToHex(), dimensionToPx()],
}),
],
})

Output:

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

Use a selector function to target [data-theme] or other modifier-based selectors:

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

Output:

:root {
--color-brand-primary: #0066cc;
}
[data-theme="dark"] {
--color-brand-primary: #66aaff;
}

When preserveReferences is true, aliases emit var(--other-token) instead of resolved values:

css({
name: 'refs',
file: 'tokens.css',
preserveReferences: true,
transforms: [nameKebabCase()],
})

Tokens that reference other tokens will output var(--token-name) rather than inlining the resolved value.

Wrap output in a media query for responsive or preference-based theming:

css({
name: 'dark-mode',
file: 'tokens.css',
mediaQuery: '(prefers-color-scheme: dark)',
selector: ':root',
transforms: [nameKebabCase(), colorToHex()],
})

Emit one file per modifier:

css({
name: 'themes',
file: 'tokens-{theme}.css',
preset: 'standalone',
transforms: [nameKebabCase(), colorToHex()],
})

The modifier preset emits a base file with all set tokens, plus separate diff files for each modifier context containing only the tokens that change:

css({
name: 'diffs',
file: '{theme}/tokens.css',
preset: 'modifier',
selector: ':root',
transforms: [nameKebabCase(), colorToHex()],
})

Produces:

  • base/tokens.css — all tokens from the resolver’s sets (colors, typography, spacing, etc.)
  • light/tokens.css — tokens that change in the light theme
  • dark/tokens.css — tokens that change in the dark theme

The base file groups tokens by set with descriptive comments, matching the structure of the bundle preset’s base output. If there are no set tokens, the base file is not emitted.