| name | tailwind-v4 |
| description | Tailwind CSS v4 patterns, CSS-first configuration, and v3 migration guide. Use when writing styles, configuring @theme variables, creating components with CVA, migrating from tailwind.config.js, or using container queries, dark mode, and new v4 utility syntax. Covers @import tailwindcss, custom properties, oklch colors, and clsx. |
| license | MIT |
| allowed-tools | Read, Grep, Glob |
| metadata | {"author":"RevealUI Studio","version":"0.1.0","website":"https://revealui.com"} |
Tailwind CSS v4 Patterns
CSS-First Configuration (No tailwind.config.js)
Tailwind v4 uses CSS instead of JavaScript for configuration:
@import "tailwindcss";
@theme {
--color-brand: #3b82f6;
--color-brand-dark: #1d4ed8;
--font-heading: "Inter", sans-serif;
--breakpoint-3xl: 1920px;
--ease-spring: cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
- No
tailwind.config.js or tailwind.config.ts needed
@theme block defines design tokens as CSS custom properties
- All theme values become utilities automatically:
bg-brand, font-heading, etc.
Theme Variables
@theme {
--color-primary: oklch(0.7 0.15 250);
--color-surface: #ffffff;
--color-surface-dark: #1a1a2e;
--spacing-gutter: 1.5rem;
--font-sans: "Inter", system-ui, sans-serif;
--font-mono: "JetBrains Mono", monospace;
--text-display: 3.5rem;
--leading-display: 1.1;
--shadow-card: 0 1px 3px oklch(0 0 0 / 0.12);
--radius-card: 0.75rem;
--animate-slide-in: slide-in 0.3s var(--ease-spring);
}
Using Theme Variables in Components
<div className="bg-primary text-surface rounded-card shadow-card">
<h1 className="font-sans text-display leading-display">Title</h1>
</div>
.custom-element {
background: var(--color-primary);
border-radius: var(--radius-card);
}
Dark Mode
@theme {
--color-surface: #ffffff;
--color-text: #1a1a2e;
}
@media (prefers-color-scheme: dark) {
:root {
--color-surface: #1a1a2e;
--color-text: #e5e5e5;
}
}
Or use the dark: variant:
<div className="bg-surface dark:bg-surface-dark text-text dark:text-text-light">
New v4 Syntax
<div className="@container">
<div className="@lg:grid-cols-3">Content</div>
</div>
<div className="bg-(--color-brand/50)">50% opacity brand</div>
<div className="group/card">
<div className="group-hover/card:opacity-100">Shows on card hover</div>
</div>
<div className="has-[input:checked]:bg-blue-500">
Migration from v3
Key changes:
- Move
tailwind.config.js colors/fonts/etc. into @theme CSS block
- Remove
tailwind.config.js (or keep minimal for plugins)
- Replace
@tailwind base/components/utilities with @import "tailwindcss"
- Update color opacity syntax:
bg-blue-500/50 stays the same
- Custom properties:
theme() function replaced by var(--color-*) in CSS
Component Patterns (CVA)
import { cva, type VariantProps } from 'class-variance-authority';
const button = cva(
'inline-flex items-center justify-center rounded-md font-medium transition-colors',
{
variants: {
intent: {
primary: 'bg-primary text-white hover:bg-primary-dark',
secondary: 'bg-surface border border-gray-300 hover:bg-gray-50',
danger: 'bg-red-600 text-white hover:bg-red-700',
},
size: {
sm: 'h-8 px-3 text-sm',
md: 'h-10 px-4 text-sm',
lg: 'h-12 px-6 text-base',
},
},
defaultVariants: {
intent: 'primary',
size: 'md',
},
}
);
type ButtonProps = VariantProps<typeof button> & React.ButtonHTMLAttributes<HTMLButtonElement>;
Common Mistakes to Avoid
- Don't create a
tailwind.config.js in v4 — use @theme in CSS
- Don't use
@apply excessively — prefer utility classes directly
- Don't hardcode colors — define in
@theme for consistency
- Don't use arbitrary values when a theme token exists
- Don't forget to set up
clsx or cn() for conditional class merging
- Don't list broad prefix aliases before specific subpath aliases in Vite config
Skill by RevealUI Studio — the agentic business runtime.