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);
		
  1. theme variable
  2. inlines as 8px
  3. default readable classes: .demo-root
  4. compact classes and vars: .a, --a
  1. Bind. createDistillery takes a prefix and a nested theme tree; it derives tokens and themeVars.
  2. Author. Tagged templates (css, rule, media, variants) record every token and var they touch.
  3. Collect. A StylesCollector keeps the entries a render actually reached. Unused variants and unread custom properties drop out.
  4. Emit. renderStyles writes CSS in readable or compact names, for a full stylesheet or a single artifact.
Mermaid diagram

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. tokens is the tree you passed in. The engine never invents a palette.
  • Emotion-shaped opt-in. @elastic/distillate/emotion is css / cx / injectGlobal over the same registry for incremental adoption.
  • Testable CSS. @elastic/distillate/testing asserts every var(...) has a matching declaration.

See Distillate vs CSS-in-JS for a side-by-side comparison with Emotion, CSS Modules, vanilla-extract, and Tailwind.