Distillate
@elastic/distillate is a CSS style engine for component libraries. You author styles once, against your own tokens. The engine emits a public stylesheet with stable names, or a tree-shaken compact payload for HTML that leaves the app.
One runtime dependency, for emotion-style syntax: stylis 4.4.0. No brand is baked in.
import { createDistillery, cq, lightDark } from '@elastic/distillate';
const distillery = createDistillery({
prefix: 'eui',
themeScope: '.eui-view',
theme: {
colors: { ink: lightDark('#111', '#eee') },
gap: cq('8px', '2cqi'),
},
});
const demo = distillery.createStyleModule('demo', ({ css, tokens }) => ({
root: css`
color: ${tokens.colors.ink};
padding: ${tokens.gap};
`,
}));
distillery.renderStyles(distillery.stylesheetCollector());
const collector = distillery.artifactCollector('compact');
collector.use(demo.handles.root);
distillery.renderStyles(collector);
- theme variable
- inlines as
8px - default readable classes:
.demo-root - compact classes and vars:
.a,--a
- Bind.
createDistillerytakes a prefix and a nested theme tree; it derivestokensandthemeVars. - Author. Tagged templates (
css,rule,media,variants) record every token and var they touch. - Collect. A
StylesCollectorkeeps the entries a render actually reached. Unused variants and unread custom properties drop out. - Emit.
renderStyleswrites CSS in readable or compact names, for a full stylesheet or a single artifact.
Distillate is for component library authors who need the same authored styles to work two ways: a public stylesheet with stable names for host applications, and a compact self-contained CSS payload for HTML that leaves the app (emails, AI reply cards, SVG renders, exported reports).
- Two outputs from one source. Readable names for apps; compact names for payloads where HTML and CSS travel together.
- Reachability, not static analysis. Collection runs during a real render — class-name resolution is the side effect that builds the collected set. Unused entries and unread theme tokens drop out automatically.
- Your tokens.
tokensis the tree you passed in. The engine never invents a palette. - Emotion-shaped opt-in.
@elastic/distillate/emotioniscss/cx/injectGlobalover the same registry for incremental adoption. - Testable CSS.
@elastic/distillate/testingasserts everyvar(...)has a matching declaration.
See Distillate vs CSS-in-JS for a side-by-side comparison with Emotion, CSS Modules, vanilla-extract, and Tailwind.