Skip to content

Tailwind CSS

helix-ui is not a Tailwind replacement. The two solve different problems, and a lot of teams want both:

  • helix-ui ships components, tokens, an a11y baseline, and a theme engine.
  • Tailwind ships layout utilities (flex, grid, gap-4, md:px-6) that are awkward to express any other way.

This page shows how to use them together without fighting either.

Install both

Terminal window
npm install @helix-ui/core @helix-ui/tokens @helix-ui/icons tailwindcss postcss autoprefixer
npx tailwindcss init -p

Mirror helix-ui tokens into Tailwind’s theme

This is the key step. Tailwind’s theme.extend reads helix-ui’s token variables so utilities like bg-brand-500 resolve to the same OKLCH color helix-ui’s components use.

tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: [
'./index.html',
'./src/**/*.{ts,tsx,js,jsx}',
// Match helix-ui's own component source so Tailwind doesn't purge
// utilities that exist inside @helix-ui/core's CSS files.
'./node_modules/@helix-ui/core/dist/**/*.{js,mjs,css}',
],
theme: {
extend: {
colors: {
brand: {
50: 'oklch(var(--helix-ui-color-brand-50-l) var(--helix-ui-color-brand-50-c) var(--helix-ui-color-brand-50-h))',
// ... or simpler: read the CSS var directly
DEFAULT: 'var(--helix-ui-color-bg-action-brand-default)',
},
// ...repeat for neutral, success, warning, danger
},
spacing: {
// helix-ui scales spacing via the density gene. Don't hard-code
// here — point at the CSS variable.
1: 'var(--helix-ui-space-1)',
2: 'var(--helix-ui-space-2)',
3: 'var(--helix-ui-space-3)',
4: 'var(--helix-ui-space-4)',
6: 'var(--helix-ui-space-6)',
8: 'var(--helix-ui-space-8)',
},
borderRadius: {
sm: 'var(--helix-ui-radius-sm)',
DEFAULT: 'var(--helix-ui-radius-md)',
lg: 'var(--helix-ui-radius-lg)',
},
fontFamily: {
sans: 'var(--helix-ui-font-family-sans)',
mono: 'var(--helix-ui-font-family-mono)',
},
},
},
// Tailwind's reset can clash with helix-ui's component CSS. Disable
// preflight and either rely on helix-ui's reset or write your own.
corePlugins: { preflight: false },
};

The corePlugins.preflight: false is the one non-obvious bit — Tailwind’s CSS reset (@tailwind base) nukes some defaults helix-ui relies on. If you’re moving an existing Tailwind project to helix-ui, this line prevents a wave of subtle visual breakage.

Import both stylesheets

src/index.css
@import '@helix-ui/tokens/css';
@import '@helix-ui/core/styles.css';
@tailwind components;
@tailwind utilities;

helix-ui’s stylesheet ships first so Tailwind utilities can override.

Use them in tandem

import { Button, Card, Stack } from '@helix-ui/core';
function PaymentRow({ amount, status }: Props) {
return (
// helix-ui Card + Stack handle the design system. Tailwind handles
// the page layout.
<Card className="md:col-span-2">
<Stack direction="row" align="center" justify="between" className="gap-4">
<div className="text-brand">{amount}</div>
<Button>Pay</Button>
</Stack>
</Card>
);
}

Rule of thumb:

Use helix-ui forUse Tailwind for
Buttons, inputs, cards, dialogs, popoversGrid spans, responsive breakpoints
Color, radius, typography, motionMargins, padding overrides at breakpoints
Anything that should be themable via DNAAnything that’s “just layout”

When the cascade fights

If you find yourself writing !bg-brand-500 to override a helix-ui component’s background, that’s a smell — the right move is to pass helix-ui’s own variant / tone prop. Tailwind override should be for layout properties, not visual ones.

// ❌ Fighting the cascade
<Button className="!bg-purple-600">Save</Button>
// ✅ Use helix-ui's API
<Button tone="brand" variant="solid">Save</Button>
// ✅ Tailwind for layout
<Button className="w-full md:w-auto">Save</Button>

What you give up

  • Two stylesheets to ship. Together they’re ~30 KB gzip. Tradeoff for the breadth.
  • Two mental models for color. helix-ui’s tokens are the source of truth; the Tailwind names mirror them. Don’t author colors in two places.

Migrating from Tailwind-only

A typical path:

  1. Install helix-ui.
  2. Set corePlugins.preflight: false.
  3. Replace your hand-rolled <button className="bg-blue-600 px-4 py-2 ...">s with <Button>.
  4. Keep your layout utilities (grid, flex, md:*) — they’re still useful.
  5. Move your colors into helix-ui tokens so DNA themes Just Work.

The migration is incremental. You don’t have to do it all at once.