| name | styling-guidelines |
| description | Tailwind CSS v4 styling guidelines - use @theme blocks for configuration, hsl(var(--color-x)) for colors, never hardcode values, use responsive utilities |
Tailwind CSS v4 Styling Guidelines
This skill ensures consistent styling practices using Tailwind CSS v4 with CSS variables and modern design patterns.
Tailwind CSS v4 Setup
CSS Configuration
Use @import instead of @tailwind directives:
/* src/index.css */
@import "tailwindcss";
@theme {
/* Your theme configuration here */
}
Vite Configuration
Install and use the Vite plugin:
npm install -D @tailwindcss/vite
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [react(), tailwindcss()],
});
Key Differences from v3
- No
tailwind.config.jsneeded - use@themeblocks in CSS - Automatic content detection (no content array configuration)
- Use
@import "tailwindcss"instead of@tailwinddirectives - Built-in Vite plugin:
@tailwindcss/vite
Theme System
Defining Theme Variables
All theme variables are defined in the @theme block in src/index.css:
@theme {
/* Border radius */
--radius: 0.5rem;
/* Colors - using HSL format for v4 */
--color-background: 0 0% 100%;
--color-foreground: 0 0% 3.9%;
--color-primary: 0 0% 9%;
--color-primary-foreground: 0 0% 98%;
--color-secondary: 0 0% 96.1%;
--color-secondary-foreground: 0 0% 9%;
--color-destructive: 0 84.2% 60.2%;
--color-border: 0 0% 89.8%;
--color-ring: 0 0% 3.9%;
}
HSL Color Format
Colors MUST be defined in HSL format without the hsl() wrapper:
/* CORRECT */
--color-primary: 221 83% 53%;
--color-accent: 142 76% 36%;
/* INCORRECT */
--color-primary: hsl(221, 83%, 53%);
--color-primary: #3B82F6;
Using Theme Colors
Use the hsl(var(--color-name)) pattern with Tailwind utilities:
/* CORRECT - Using CSS variables */
<div className="bg-[hsl(var(--color-primary))]" />
<div className="text-[hsl(var(--color-foreground))]" />
<div className="border-[hsl(var(--color-border))]" />
/* CORRECT - With opacity */
<div className="bg-[hsl(var(--color-primary)/0.5)]" />
<div className="bg-[hsl(var(--color-accent)/0.2)]" />
/* INCORRECT - Hardcoded colors */
<div className="bg-blue-500" />
<div className="text-[#3B82F6]" />
<div className="border-gray-200" />
Border Radius Tokens
Use semantic radius tokens defined in the theme:
@theme {
--radius: 0.5rem;
/* Additional radius tokens can reference the base */
--radius-lg: calc(var(--radius) * 1.5);
--radius-sm: calc(var(--radius) * 0.5);
}
/* CORRECT - Using Tailwind utilities that reference --radius */
<div className="rounded-lg" /> /* Uses --radius-lg */
<div className="rounded-md" /> /* Uses --radius */
<div className="rounded-sm" /> /* Uses --radius-sm */
/* INCORRECT - Hardcoded values */
<div className="rounded-[8px]" />
<div className="rounded-[12px]" />
Never Hardcode Values
Color Hardcoding (DO NOT DO)
/* ❌ WRONG - Hardcoded Tailwind colors */
<button className="bg-blue-500 hover:bg-blue-600">Click me</button>
<div className="text-gray-900 border-gray-200">Content</div>
/* ❌ WRONG - Hardcoded hex values */
<div className="bg-[#3B82F6] text-[#1F2937]">Content</div>
/* ✅ CORRECT - Use theme variables */
<button className="bg-[hsl(var(--color-primary))] hover:bg-[hsl(var(--color-primary)/0.9)]">
Click me
</button>
<div className="text-[hsl(var(--color-foreground))] border-[hsl(var(--color-border))]">
Content
</div>
Spacing Hardcoding (DO NOT DO)
/* ❌ WRONG - Arbitrary pixel values */
<div className="p-[24px] m-[16px] gap-[12px]">Content</div>
/* ✅ CORRECT - Use Tailwind spacing scale */
<div className="p-6 m-4 gap-3">Content</div>
Border Radius Hardcoding (DO NOT DO)
/* ❌ WRONG - Arbitrary radius values */
<div className="rounded-[8px]">Content</div>
<div className="rounded-[12px]">Content</div>
/* ✅ CORRECT - Use semantic tokens */
<div className="rounded-lg">Content</div>
<div className="rounded-xl">Content</div>
When to Use Tailwind Utilities vs CSS Variables
Use Tailwind Utilities For:
- Spacing:
p-4,m-6,gap-8,space-y-4 - Responsive breakpoints:
md:grid-cols-2,lg:flex-row - Flex/Grid layouts:
flex,grid,justify-between,items-center - Typography:
text-xl,font-semibold,leading-relaxed - Standard utilities:
rounded-lg,shadow-lg,transition-all
Use CSS Variables For:
- Theme colors: All colors should use CSS variables
- Custom radii: Brand-specific border radius values
- Brand-specific values: Any value that might change with themes
Combine Both:
Use utility prefixes with variable values:
/* Color utilities with variables */
<div className="bg-[hsl(var(--color-primary))]" />
<div className="text-[hsl(var(--color-foreground))]" />
<div className="border-[hsl(var(--color-border))]" />
/* With opacity modifiers */
<div className="bg-[hsl(var(--color-primary)/0.5)]" />
<div className="shadow-[0_0_20px_hsl(var(--color-primary)/0.3)]" />
Responsive Design Patterns
Mobile-First Approach
Always start with base (mobile) styles, then add responsive modifiers:
/* CORRECT - Mobile first */
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
{/* Grid items */}
</div>
<div className="flex flex-col md:flex-row gap-4 md:gap-6 lg:gap-8">
{/* Flex items */}
</div>
/* INCORRECT - Desktop first (avoid) */
<div className="grid grid-cols-3 md:grid-cols-2 grid-cols-1">
{/* This is backwards */}
</div>
Breakpoint Reference
Tailwind CSS v4 uses the same default breakpoints as v3:
| Breakpoint | Min Width | Example |
|---|---|---|
sm: |
640px | sm:text-lg |
md: |
768px | md:grid-cols-2 |
lg: |
1024px | lg:grid-cols-3 |
xl: |
1280px | xl:max-w-7xl |
2xl: |
1536px | 2xl:px-0 |
Real Example from This Project
From /Users/julien.hovan/Desktop/Internals/Vite-React-Typescript-Boiler/src/pages/Home.tsx:
{/* Responsive grid - 1 column mobile, 2 tablet, 3 desktop */}
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{features.map((feature) => (
<Card key={feature.title}>
{/* Card content */}
</Card>
))}
</div>
{/* Responsive text sizing */}
<h1 className="text-6xl sm:text-7xl md:text-8xl">
{APP_NAME}
</h1>
{/* Responsive spacing */}
<div className="mx-auto max-w-4xl">
<p className="text-xl sm:text-2xl">
Subtitle text
</p>
</div>
Gradient Patterns
Linear Gradients
/* Basic gradient */
<div className="bg-gradient-to-r from-blue-500 to-purple-500">
Content
</div>
/* With direction variants */
<div className="bg-gradient-to-br from-blue-500 to-purple-500"> {/* bottom-right */}
<div className="bg-gradient-to-tr from-blue-500 to-purple-500"> {/* top-right */}
<div className="bg-gradient-to-bl from-blue-500 to-purple-500"> {/* bottom-left */}
Gradients with Custom Colors
Use CSS variables in gradients:
/* CORRECT - Using theme variables */
<div className="bg-gradient-to-br from-[hsl(var(--color-primary))] to-[hsl(var(--color-secondary))]">
Content
</div>
/* With via color */
<div className="bg-gradient-to-r from-[hsl(var(--color-primary))] via-[hsl(var(--color-accent))] to-[hsl(var(--color-secondary))]">
Content
</div>
Gradients with Opacity
/* With opacity modifiers */
<div className="bg-gradient-to-br from-blue-400/20 via-purple-400/20 to-pink-400/20">
Content
</div>
/* With blur for background effects */
<div className="h-[600px] w-[600px] rounded-full bg-gradient-to-br from-blue-400/20 via-purple-400/20 to-pink-400/20 blur-3xl">
{/* Blurred gradient blob */}
</div>
Real Examples from This Project
From /Users/julien.hovan/Desktop/Internals/Vite-React-Typescript-Boiler/src/pages/Home.tsx:
{/* Gradient background blobs */}
<div className="absolute left-1/2 top-0 -translate-x-1/2 -translate-y-1/2">
<div className="h-[600px] w-[600px] rounded-full bg-gradient-to-br from-blue-400/20 via-purple-400/20 to-pink-400/20 blur-3xl" />
</div>
{/* Text gradient */}
<h1 className="bg-gradient-to-r from-gray-900 via-blue-900 to-purple-900 bg-clip-text text-transparent">
{APP_NAME}
</h1>
{/* Icon gradient background */}
<div className="rounded-full bg-gradient-to-br from-blue-500 to-purple-600 p-3 shadow-lg shadow-blue-500/50">
<Sparkles className="h-8 w-8 text-white" />
</div>
{/* Card hover effect with dynamic gradient */}
<div className={`bg-gradient-to-br ${feature.gradient} opacity-0 group-hover:opacity-100`} />
Spacing Conventions
Tailwind Spacing Scale
Tailwind uses a consistent 4px base unit:
| Class | Value | Use Case |
|---|---|---|
p-1 |
4px | Tiny spacing |
p-2 |
8px | Small spacing |
p-3 |
12px | Compact spacing |
p-4 |
16px | Standard spacing |
p-6 |
24px | Medium spacing |
p-8 |
32px | Large spacing |
p-12 |
48px | Extra large spacing |
p-16 |
64px | Section spacing |
p-32 |
128px | Hero section spacing |
Consistent Spacing Patterns
/* Vertical stacks - use space-y */
<div className="space-y-4">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
/* Grid gaps - use gap */
<div className="grid grid-cols-3 gap-6">
<div>Card 1</div>
<div>Card 2</div>
<div>Card 3</div>
</div>
/* Flex gaps - use gap */
<div className="flex gap-4">
<button>Button 1</button>
<button>Button 2</button>
</div>
Real Examples from This Project
From /Users/julien.hovan/Desktop/Internals/Vite-React-Typescript-Boiler/src/pages/Home.tsx:
{/* Large section spacing */}
<div className="space-y-32">
{/* Hero Section */}
<div className="relative overflow-hidden">
<div className="px-6 py-32 text-center">
{/* Content */}
</div>
</div>
{/* Features Grid with consistent gap */}
<div className="grid gap-8 md:grid-cols-2 lg:grid-cols-3">
{/* Cards */}
</div>
</div>
{/* Card header spacing */}
<CardHeader className="space-y-4">
{/* Icon and badge */}
<div className="flex items-start justify-between">
{/* Content */}
</div>
{/* Title and description */}
</CardHeader>
Base Layer Styles
Apply theme variables to base elements using the @layer base directive:
@layer base {
* {
border-color: hsl(var(--color-border));
}
body {
background-color: hsl(var(--color-background));
color: hsl(var(--color-foreground));
}
}
This ensures:
- Default border colors use your theme
- Body background and text use theme variables
- Consistent styling across the entire app
Quick Reference: Common Patterns
✅ DO
/* Use CSS variables for colors */
<div className="bg-[hsl(var(--color-primary))]" />
/* Use Tailwind spacing scale */
<div className="p-6 m-4 gap-8" />
/* Use semantic border radius */
<div className="rounded-lg" />
/* Mobile-first responsive */
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3" />
/* Gradients with opacity */
<div className="bg-gradient-to-br from-blue-400/20 via-purple-400/20 to-pink-400/20" />
/* Combine utilities with variables */
<div className="text-[hsl(var(--color-foreground))] hover:text-[hsl(var(--color-primary))]" />
❌ DON'T
/* Don't hardcode Tailwind colors */
<div className="bg-blue-500" />
/* Don't use arbitrary pixel values */
<div className="p-[24px] m-[16px]" />
/* Don't hardcode border radius */
<div className="rounded-[8px]" />
/* Don't use hex colors */
<div className="bg-[#3B82F6]" />
/* Don't define gradients without opacity when used as overlays */
<div className="bg-gradient-to-br from-blue-400 via-purple-400 to-pink-400" />
Project-Specific Examples
Navigation (from MainLayout.tsx)
<header className="sticky top-0 z-50 border-b border-gray-200 bg-white/95 backdrop-blur supports-[backdrop-filter]:bg-white/60">
<div className="mx-auto max-w-7xl px-8 py-4">
<nav className="flex items-center justify-end">
<div className="flex items-center gap-8">
<Link className="relative px-4 py-2 text-base font-medium transition-colors hover:text-blue-600">
Home
</Link>
</div>
</nav>
</div>
</header>
Hero Section Pattern
<div className="relative overflow-hidden">
{/* Background gradient blobs */}
<div className="absolute inset-0 -z-10">
<div className="absolute left-1/2 top-0 -translate-x-1/2 -translate-y-1/2">
<div className="h-[600px] w-[600px] rounded-full bg-gradient-to-br from-blue-400/20 via-purple-400/20 to-pink-400/20 blur-3xl" />
</div>
</div>
<div className="relative px-6 py-32 text-center">
{/* Content */}
</div>
</div>
Interactive Card Pattern
<Card className="group relative overflow-hidden border-2 transition-all duration-300 hover:-translate-y-2 hover:border-transparent hover:shadow-2xl">
{/* Gradient border effect on hover */}
<div className={`absolute inset-0 -z-10 bg-gradient-to-br ${feature.gradient} opacity-0 transition-opacity duration-300 group-hover:opacity-100`} />
<div className="absolute inset-[2px] -z-10 rounded-lg bg-white" />
<CardHeader className="space-y-4">
{/* Content */}
</CardHeader>
</Card>
Verification Checklist
Before committing styled components, verify:
- No hardcoded Tailwind color classes (e.g.,
bg-blue-500) - No hardcoded hex/rgb colors (e.g.,
bg-[#3B82F6]) - All theme colors use
hsl(var(--color-name))pattern - Spacing uses Tailwind scale (not arbitrary values like
p-[24px]) - Border radius uses semantic tokens (not
rounded-[8px]) - Responsive design is mobile-first
- Gradients use consistent opacity patterns for overlays
- All custom colors are defined in
@themeblock
Additional Resources
- Tailwind CSS v4 Docs: https://tailwindcss.com/docs/v4-beta
- Project Theme File:
/Users/julien.hovan/Desktop/Internals/Vite-React-Typescript-Boiler/src/index.css - Vite Config:
/Users/julien.hovan/Desktop/Internals/Vite-React-Typescript-Boiler/vite.config.ts - Example Components: Check
src/pages/Home.tsxandsrc/layouts/MainLayout.tsxfor reference implementations