Tailwind CSS v4 patterns with CSS-first configuration, @theme directive, design system integration, and utility-first styling for Next.js applications.
Tailwind CSS v4 patterns with CSS-first configuration for Next.js applications.
Reference Files:
- css-first-config.md - CSS-first configuration with @theme
- utility-patterns.md - Common utility class patterns
- design-system.md - Integration with @szum-tech/design-system
- v4-migration.md - Breaking changes from v3
- - Responsive design patterns
This project uses Tailwind CSS v4 with CSS-first configuration:
/* app/globals.css */
@import "tailwindcss";
@import "@szum-tech/design-system/tailwind/global.css";
@source "../node_modules/@szum-tech/design-system";
Key v4 Changes:
tailwind.config.ts file - configuration in CSS@import "tailwindcss" replaces @tailwind directives@theme directive for customization@source for scanning additional directories/* app/globals.css */
@import "tailwindcss";
@theme {
--color-brand-50: oklch(0.97 0.02 250);
--color-brand-500: oklch(0.55 0.2 250);
--color-brand-900: oklch(0.25 0.1 250);
}
// Usage in components
<div className="bg-brand-500 text-brand-50">Brand colored box</div>
@theme {
--spacing-18: 4.5rem;
--spacing-128: 32rem;
}
<div className="p-18 w-128">Custom spacing</div>
@theme {
--font-display: "Inter", sans-serif;
--font-mono: "Fira Code", monospace;
}
<h1 className="font-display">Heading</h1>
<code className="font-mono">Code</code>
Tailwind v4 moves configuration from JavaScript to CSS:
| v3 (JavaScript) | v4 (CSS) |
|---|---|
tailwind.config.ts | @theme in CSS |
@tailwind base/components/utilities | @import "tailwindcss" |
content: ['./src/**/*.tsx'] | Automatic detection + @source |
theme.extend.colors | --color-* variables |
The @theme directive defines design tokens:
@theme {
/* Colors */
--color-primary: oklch(0.6 0.2 250);
/* Spacing */
--spacing-gutter: 1.5rem;
/* Typography */
--font-heading: "Poppins", sans-serif;
--text-hero: 4rem;
--leading-hero: 1.1;
/* Breakpoints */
--breakpoint-3xl: 1920px;
/* Animations */
--ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
Scan additional directories for class names:
/* Scan design system package */
@source "../node_modules/@szum-tech/design-system";
/* Scan specific files */
@source "./content/**/*.mdx";
| Change | v3 | v4 | Action |
|---|---|---|---|
| Ring width | ring = 3px | ring = 1px | Use ring-3 for old behavior |
| Ring color | ring = blue-500 | ring = currentColor | Add ring-blue-500 explicitly |
| Outline | No default width | outline = 1px solid | Explicit if needed |
| Import | @tailwind base | @import "tailwindcss" | Update imports |
This project uses @szum-tech/design-system:
/* Import order matters */
@import "tailwindcss";
@import "@szum-tech/design-system/tailwind/global.css";
@source "../node_modules/@szum-tech/design-system";
Component Usage:
import { Button, Card } from "@szum-tech/design-system";
// Components come pre-styled
<Button variant="primary">Click me</Button>
<Card className="p-6">Custom padding on card</Card>
// Mobile-first approach
<div className="p-4 md:p-6 lg:p-8">
<h1 className="text-xl md:text-2xl lg:text-4xl">Responsive heading</h1>
</div>
<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
Supports dark mode
</div>
<button
className="
bg-blue-500
hover:bg-blue-600
focus:ring-2
focus:ring-blue-500
disabled:opacity-50
disabled:cursor-not-allowed
"
>
Interactive button
</button>
<div className="group">
<span className="group-hover:text-blue-500">
Changes on parent hover
</span>
</div>
<input className="peer" />
<span className="peer-invalid:text-red-500">
Shows when input is invalid
</span>
| Purpose | Location |
|---|---|
| Global styles | app/globals.css |
| Design tokens | @theme in globals.css |
| Component styles | Inline with className |
react-19-compiler - Component patterns for stylingstorybook-testing - Testing styled componentsaccessibility-audit - Color contrast, focus states