Utility Classes, Layout, Flexbox, Grid, Spacing, Typography, Colors, Animations — the complete Tailwind CSS 4 reference.
<!-- ── Every utility class maps to a CSS property ── -->
<!-- Traditional CSS vs Tailwind -->
<!-- Traditional -->
<button class="btn btn-primary btn-lg">Click</button>
<!-- Tailwind -->
<button class="bg-blue-600 text-white font-bold py-3 px-6 rounded-lg
hover:bg-blue-700 active:bg-blue-800 transition-colors">
Click
</button>
<!-- ── Responsive Prefixes ── -->
<!-- sm: 640px+ | md: 768px+ | lg: 1024px+ | xl: 1280px+ | 2xl: 1536px+ -->
<div class="w-full md:w-1/2 lg:w-1/3">
Responsive width
</div>
<!-- ── Dark Mode ── -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
Adapts to system or manual theme
</div>
<!-- ── State Variants ── -->
<button class="bg-blue-600 hover:bg-blue-700 focus:ring-2 focus:ring-blue-500
active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed
transition-all">
Interactive button
</button>
<!-- ── Arbitrary Values ── -->
<div class="w-[275px] top-[117px] text-[14px] bg-[#1da1f2]">
Any value with brackets
</div><!-- ── Group & Peer Variants ── -->
<div class="group">
<h3 class="text-gray-500 group-hover:text-blue-600 transition-colors">
Title changes color on parent hover
</h3>
<p class="opacity-0 group-hover:opacity-100 translate-y-2
group-hover:translate-y-0 transition-all">
Content fades in
</p>
</div>
<!-- ── Peer Variants ── -->
<form>
<input class="peer ..." placeholder="Email" />
<label class="peer-placeholder-shown:top-1/2 peer-focus:top-0
peer-placeholder-shown:text-gray-400 peer-focus:text-blue-600
transition-all">
Email Address
</label>
</form>
<!-- ── Container Queries ── -->
<div class="@container">
<div class="flex flex-col @md:flex-row">
Stacks on small containers, row on large
</div>
</div>
<!-- ── Important Modifier ── -->
<div class="!text-red-500">Overrides other styles</div>| Variant | Example | Description | ||
|---|---|---|---|---|
| Responsive | md:flex | Applies at breakpoint+ | ||
| State | hover: | focus: | active: | User interaction |
| Theme | dark: | Opposite theme mode | ||
| Group | group-hover: | Based on parent hover | ||
| Peer | peer-focus: | Based on sibling state | ||
| Container | @lg: | Based on container size | ||
| Pseudo | first: | last: | odd: | CSS pseudo-classes |
| Not | not-hover: | Inverse of variant | ||
| ARIA | aria-checked: | Based on ARIA attributes | ||
| Data | data-[open]: | Based on data attributes |
/* ── Tailwind CSS 4: Custom Variants ── */
@import "tailwindcss";
/* Custom variant */
@custom-variant --any (&:where(*));
/* Custom modifier */
@custom-variant h2 (&:where(h2));
/* Use in HTML */
<h2 class="text-3xl font-bold h2:text-4xl">
Heading
</h2>tailwind.config.js — configuration is done directly in CSS with @theme directives. The engine is written in Rust (Oxide) for 10x faster build times.<!-- ── Flex Container ── -->
<div class="flex flex-col md:flex-row">
<div>Column on mobile, row on desktop</div>
</div>
<!-- ── Flex Direction ── -->
<div class="flex flex-row"> <!-- left to right (default) -->
<div class="flex flex-row-reverse"> <!-- right to left -->
<div class="flex flex-col"> <!-- top to bottom -->
<div class="flex flex-col-reverse"> <!-- bottom to top -->
<!-- ── Justify Content (main axis) ── -->
<div class="flex justify-start"> <!-- pack to start -->
<div class="flex justify-end"> <!-- pack to end -->
<div class="flex justify-center"> <!-- center -->
<div class="flex justify-between"> <!-- space between -->
<div class="flex justify-around"> <!-- space around -->
<div class="flex justify-evenly"> <!-- space evenly -->
<!-- ── Align Items (cross axis) ── -->
<div class="flex items-start"> <!-- top -->
<div class="flex items-end"> <!-- bottom -->
<div class="flex items-center"> <!-- center -->
<div class="flex items-baseline"> <!-- baseline -->
<div class="flex items-stretch"> <!-- stretch (default) -->
<!-- ── Perfect Centering ── -->
<div class="flex items-center justify-center min-h-screen">
Centered content
</div>
<!-- ── Flex Wrap ── -->
<div class="flex flex-wrap gap-4">
Items wrap to next line
</div>
<!-- ── Flex Grow, Shrink, Basis ── -->
<div class="flex-1">Grows to fill space</div>
<div class="flex-none">Fixed size</div>
<div class="flex-[2]">Double grow ratio</div>
<div class="basis-64">Initial size 256px</div><!-- ── Navbar ── -->
<nav class="flex items-center justify-between px-6 py-4">
<div class="text-xl font-bold">Logo</div>
<div class="flex items-center gap-4">
<a class="hover:text-blue-600">Home</a>
<a class="hover:text-blue-600">About</a>
<a class="hover:text-blue-600">Contact</a>
</div>
<button class="bg-blue-600 text-white px-4 py-2 rounded">
Sign Up
</button>
</nav>
<!-- ── Card Grid (auto-fill) ── -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div class="bg-white rounded-xl shadow p-6">Card 1</div>
<div class="bg-white rounded-xl shadow p-6">Card 2</div>
<div class="bg-white rounded-xl shadow p-6">Card 3</div>
</div>
<!-- ── Sticky Footer ── -->
<div class="flex flex-col min-h-screen">
<header class="flex-none">Header</header>
<main class="flex-1">Content</main>
<footer class="flex-none">Footer</footer>
</div>
<!-- ── Media Object ── -->
<div class="flex items-start gap-4">
<img class="w-12 h-12 rounded-full flex-none" />
<div class="flex-1 min-w-0">
<h4 class="font-semibold truncate">Title</h4>
<p class="text-gray-600 text-sm">Description text</p>
</div>
</div>| Class | CSS Value | Description |
|---|---|---|
| block | display: block | Block element |
| inline-block | display: inline-block | Inline block |
| inline | display: inline | Inline element |
| flex | display: flex | Flexbox container |
| inline-flex | display: inline-flex | Inline flexbox |
| grid | display: grid | CSS Grid container |
| inline-grid | display: inline-grid | Inline grid |
| hidden | display: none | Hide element |
| table | display: table | Table display |
| Class | CSS Value | Use Case |
|---|---|---|
| static | position: static | Default flow |
| relative | position: relative | Offset container |
| absolute | position: absolute | Positioned relative to parent |
| fixed | position: fixed | Fixed to viewport |
| sticky | position: sticky | Sticky on scroll |
| inset-0 | top/right/bottom/left: 0 | Fill parent |
| top-4 | top: 1rem | Offset from top |
| z-10 | z-index: 10 | Stack order |
| z-50 | z-index: 50 | Modals, dropdowns |
<!-- ── Basic Grid ── -->
<div class="grid grid-cols-3 gap-4">
<div>1</div><div>2</div><div>3</div>
</div>
<!-- ── Responsive Grid ── -->
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
Auto responsive columns
</div>
<!-- ── Auto-fit Grid (no media queries!) ── -->
<div class="grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-6">
Each column is at least 250px, grows to fill
</div>
<!-- ── Grid with Sidebar ── -->
<div class="grid grid-cols-[250px_1fr] gap-6">
<aside>Sidebar</aside>
<main>Content</main>
</div>
<!-- ── Holy Grail Layout ── -->
<div class="grid grid-cols-[200px_1fr_200px] grid-rows-[auto_1fr_auto] min-h-screen">
<header class="col-span-3">Header</header>
<nav>Nav</nav>
<main>Content</main>
<aside>Sidebar</aside>
<footer class="col-span-3">Footer</footer>
</div>
<!-- ── Span Multiple Columns/Rows ── -->
<div class="grid grid-cols-4 grid-rows-3 gap-4">
<div class="col-span-2 row-span-1">Wide item</div>
<div class="col-span-1 row-span-2">Tall item</div>
<div class="col-start-3 col-end-5">Span columns 3-4</div>
</div><!-- ── Named Grid Areas ── -->
<div class="grid grid-rows-[auto_1fr_auto] h-screen"
style="grid-template-areas:
'header header header'
'nav main aside'
'footer footer footer'">
<header style="grid-area: header">Header</header>
<nav style="grid-area: nav">Nav</nav>
<main style="grid-area: main">Main</main>
<aside style="grid-area: aside">Aside</aside>
<footer style="grid-area: footer">Footer</footer>
</div>
<!-- ── Grid Alignment ── -->
<div class="grid justify-items-center"> <!-- center columns -->
<div class="grid items-center"> <!-- center rows -->
<div class="grid place-items-center"> <!-- center both -->
<div class="grid justify-content-center"> <!-- center grid itself -->
<div class="grid items-end"> <!-- align to bottom -->
<!-- ── Subgrid (Tailwind 4) ── -->
<div class="grid grid-cols-3 gap-4">
<div class="col-span-3 grid grid-cols-subgrid gap-4">
<div>Aligned with parent grid</div>
<div>Aligned with parent grid</div>
<div>Aligned with parent grid</div>
</div>
</div>
<!-- ── Masonry-like (auto rows) ── -->
<div class="grid grid-cols-3 gap-4 auto-rows-[minmax(100px,auto)]">
<div class="row-span-2">Tall card</div>
<div>Normal card</div>
</div>| Class | Description |
|---|---|
| grid-cols-{n} | Number of columns |
| grid-rows-{n} | Number of rows |
| col-span-{n} | Span n columns |
| row-span-{n} | Span n rows |
| col-start-{n} | Start at column n |
| col-end-{n} | End at column n |
| gap-{n} | Gap between items (4px units) |
| gap-x-{n} | Column gap only |
| gap-y-{n} | Row gap only |
| Class | Size | Px |
|---|---|---|
| gap-0 | 0px | 0 |
| gap-1 | 0.25rem | 4px |
| gap-2 | 0.5rem | 8px |
| gap-3 | 0.75rem | 12px |
| gap-4 | 1rem | 16px |
| gap-6 | 1.5rem | 24px |
| gap-8 | 2rem | 32px |
| gap-10 | 2.5rem | 40px |
| gap-12 | 3rem | 48px |
| gap-16 | 4rem | 64px |
<!-- ── Padding (same scale for all sides) ── -->
<div class="p-0"> 0px</div>
<div class="p-1"> 4px</div>
<div class="p-2"> 8px</div>
<div class="p-3"> 12px</div>
<div class="p-4"> 16px</div>
<div class="p-5"> 20px</div>
<div class="p-6"> 24px</div>
<div class="p-8"> 32px</div>
<div class="p-10"> 40px</div>
<div class="p-12"> 48px</div>
<div class="p-16"> 64px</div>
<div class="p-20"> 80px</div>
<!-- ── Padding per Side ── -->
<div class="pt-4 pb-6 px-8"> top/bottom/left/right</div>
<div class="py-4 px-6"> vertical/horizontal</div>
<div class="ps-4 pe-6"> logical padding (start/end)</div><!-- ── Margin (same scale) ── -->
<div class="m-4"> 16px all sides</div>
<div class="mx-auto"> center horizontally (block)</div>
<div class="mt-4 mb-2 ml-6 mr-8"> individual sides</div>
<div class="my-4 mx-6"> vertical/horizontal</div>
<div class="-mt-4"> negative margin (overlap)</div>
<!-- ── Space Between (children gap via margin) ── -->
<div class="space-y-4"> <!-- vertical gap between children -->
<div>Item 1</div> <!-- 16px gap -->
<div>Item 2</div> <!-- 16px gap -->
<div>Item 3</div>
</div>
<div class="space-x-4"> <!-- horizontal gap -->
<span>Link 1</span>
<span>Link 2</span>
</div><!-- ── Width ── -->
<div class="w-full"> 100%</div>
<div class="w-screen"> 100vw</div>
<div class="w-1/2"> 50%</div>
<div class="w-1/3"> 33.33%</div>
<div class="w-2/3"> 66.67%</div>
<div class="w-px"> 1px</div>
<div class="w-64"> 16rem (256px)</div>
<div class="w-fit"> fit-content</div>
<div class="w-max"> max-content</div>
<div class="w-min"> min-content</div>
<div class="w-auto"> auto (default)</div>
<!-- ── Height ── -->
<div class="h-screen"> 100vh</div>
<div class="h-full"> 100%</div>
<div class="h-96"> 24rem (384px)</div>
<div class="min-h-screen"> min 100vh</div>
<div class="max-h-96 overflow-y-auto"> max height with scroll</div>
<!-- ── Aspect Ratio ── -->
<div class="aspect-video"> 16/9</div>
<div class="aspect-square"> 1/1</div>
<div class="aspect-[4/3]"> 4:3</div>| Class | Rem | Px |
|---|---|---|
| 0 | 0 | 0px |
| 1 | 0.25rem | 4px |
| 2 | 0.5rem | 8px |
| 3 | 0.75rem | 12px |
| 4 | 1rem | 16px |
| 6 | 1.5rem | 24px |
| 8 | 2rem | 32px |
| 10 | 2.5rem | 40px |
| 12 | 3rem | 48px |
| 16 | 4rem | 64px |
| 20 | 5rem | 80px |
| 24 | 6rem | 96px |
| 32 | 8rem | 128px |
| 40 | 10rem | 160px |
| 48 | 12rem | 192px |
| 56 | 14rem | 224px |
| 64 | 16rem | 256px |
| 72 | 18rem | 288px |
| 80 | 20rem | 320px |
| 96 | 24rem | 384px |
| Class | CSS | Behavior |
|---|---|---|
| overflow-auto | overflow: auto | Scrollbar when needed |
| overflow-hidden | overflow: hidden | Clip content |
| overflow-visible | overflow: visible | Show overflow |
| overflow-scroll | overflow: scroll | Always show scrollbar |
| overflow-x-auto | overflow-x: auto | Horizontal scroll |
| overflow-y-auto | overflow-y: auto | Vertical scroll |
| text-ellipsis | text-overflow: ellipsis | Truncate with ... |
| truncate | 3 properties | Single-line truncation |
| line-clamp-3 | -webkit-line-clamp: 3 | Multi-line truncation |
space-y-* / space-x-* to add consistent gaps between children without adding padding/margin to individual elements. This is cleaner than using flex gap when items should collapse when hidden.<!-- ── Font Size ── -->
<p class="text-xs"> 0.75rem (12px)</p>
<p class="text-sm"> 0.875rem (14px)</p>
<p class="text-base"> 1rem (16px) default</p>
<p class="text-lg"> 1.125rem (18px)</p>
<p class="text-xl"> 1.25rem (20px)</p>
<p class="text-2xl"> 1.5rem (24px)</p>
<p class="text-3xl"> 1.875rem (30px)</p>
<p class="text-4xl"> 2.25rem (36px)</p>
<p class="text-5xl"> 3rem (48px)</p>
<p class="text-6xl"> 3.75rem (60px)</p>
<p class="text-7xl"> 4.5rem (72px)</p>
<p class="text-8xl"> 6rem (96px)</p>
<p class="text-9xl"> 8rem (128px)</p>
<!-- ── Font Weight ── -->
<span class="font-thin"> 100</span>
<span class="font-extralight"> 200</span>
<span class="font-light"> 300</span>
<span class="font-normal"> 400 (default)</span>
<span class="font-medium"> 500</span>
<span class="font-semibold"> 600</span>
<span class="font-bold"> 700</span>
<span class="font-extrabold"> 800</span>
<span class="font-black"> 900</span><!-- ── Text Alignment ── -->
<p class="text-left"> Left (default for LTR)</p>
<p class="text-center"> Center</p>
<p class="text-right"> Right</p>
<p class="text-justify"> Justify</p>
<!-- ── Text Transform ── -->
<p class="uppercase"> ALL CAPS</p>
<p class="lowercase"> all lower</p>
<p class="capitalize"> Each Word</p>
<p class="normal-case"> No Transform</p>
<!-- ── Text Decoration ── -->
<span class="underline">Underlined</span>
<span class="line-through">Strikethrough</span>
<span class="overline">Overline</span>
<span class="no-underline">No decoration</span>
<!-- ── Line Height ── -->
<p class="leading-none"> 1</p>
<p class="leading-tight"> 1.25</p>
<p class="leading-snug"> 1.375</p>
<p class="leading-normal"> 1.5 (default)</p>
<p class="leading-relaxed"> 1.625</p>
<p class="leading-loose"> 2</p>
<p class="leading-[3]"> Custom: 3</p>
<!-- ── Letter Spacing ── -->
<p class="tracking-tighter"> -0.05em</p>
<p class="tracking-tight"> -0.025em</p>
<p class="tracking-normal"> 0 (default)</p>
<p class="tracking-wide"> 0.025em</p>
<p class="tracking-wider"> 0.05em</p>
<p class="tracking-widest"> 0.1em</p>
<!-- ── Text Color ── -->
<p class="text-gray-900">Dark gray</p>
<p class="text-blue-600">Blue</p>
<p class="text-red-500/50">Red with 50% opacity</p>| Class | Description |
|---|---|
| list-none | No list style |
| list-disc | Disc bullets |
| list-decimal | Numbered list |
| list-inside | Marker inside |
| list-outside | Marker outside (default) |
<!-- Placeholder styling -->
<input class="placeholder:text-gray-400
placeholder:italic" />
<!-- Selection styling -->
<p class="selection:bg-blue-500 selection:text-white">
Select this text to see custom highlight
</p><!-- ── Background Colors ── -->
<div class="bg-red-500"> Red</div>
<div class="bg-blue-600"> Blue</div>
<div class="bg-green-700"> Green</div>
<div class="bg-gray-100"> Light gray</div>
<div class="bg-gray-900"> Dark gray</div>
<!-- ── Opacity Modifier ── -->
<div class="bg-blue-500/25"> 25% opacity blue</div>
<div class="bg-blue-500/50"> 50% opacity blue</div>
<div class="bg-blue-500/75"> 75% opacity blue</div>
<!-- ── Text Colors ── -->
<p class="text-white"> White text</p>
<p class="text-gray-600"> Gray text</p>
<p class="text-blue-500"> Blue text</p>
<!-- ── Border Colors ── -->
<div class="border border-gray-300 border-red-500">
Colored border
</div>
<!-- ── Gradient Backgrounds ── -->
<div class="bg-gradient-to-r from-blue-500 to-purple-600">
Left to right gradient
</div>
<div class="bg-gradient-to-br from-green-400 via-blue-500 to-purple-600">
Diagonal gradient with via
</div>
<div class="bg-gradient-to-t from-black/50 to-transparent">
Bottom to top with opacity
</div><!-- ── Color Scale (50-950) ── -->
<!-- Each color has 11 shades -->
<!-- Red: danger, errors, alerts -->
bg-red-50 bg-red-100 bg-red-200 bg-red-300 bg-red-400
bg-red-500 bg-red-600 bg-red-700 bg-red-800 bg-red-900 bg-red-950
<!-- Blue: primary, links, info -->
bg-blue-50 bg-blue-100 bg-blue-200 bg-blue-300 bg-blue-400
bg-blue-500 bg-blue-600 bg-blue-700 bg-blue-800 bg-blue-900 bg-blue-950
<!-- Green: success, positive, nature -->
bg-green-50 bg-green-100 bg-green-200 bg-green-300 bg-green-400
bg-green-500 bg-green-600 bg-green-700 bg-green-800 bg-green-900 bg-green-950
<!-- Amber: warnings, attention -->
bg-amber-50 bg-amber-100 bg-amber-200 bg-amber-300 bg-amber-400
bg-amber-500 bg-amber-600 bg-amber-700 bg-amber-800 bg-amber-900 bg-amber-950
<!-- Gray: neutral, text, borders -->
bg-gray-50 bg-gray-100 bg-gray-200 bg-gray-300 bg-gray-400
bg-gray-500 bg-gray-600 bg-gray-700 bg-gray-800 bg-gray-900 bg-gray-950
<!-- Slate (cool gray): modern UIs -->
bg-slate-50 bg-slate-100 bg-slate-200 bg-slate-300 bg-slate-400
bg-slate-500 bg-slate-600 bg-slate-700 bg-slate-800 bg-slate-900 bg-slate-950<!-- ── Dark Mode ── -->
<!-- Method 1: class strategy (add dark to html) -->
<html class="dark">
<div class="bg-white dark:bg-gray-900">
<h1 class="text-gray-900 dark:text-white">Title</h1>
<p class="text-gray-600 dark:text-gray-300">Description</p>
</div>
<!-- Method 2: media strategy (system preference) -->
<div class="bg-white dark:bg-gray-900">
<!-- Adapts to prefers-color-scheme -->
</div>
<!-- ── Toggle Dark Mode ── -->
<button onclick="document.documentElement.classList.toggle('dark')">
Toggle Theme
</button>| Class | Mix-Blend-Mode |
|---|---|
| mix-blend-normal | Normal |
| mix-blend-multiply | Multiply |
| mix-blend-screen | Screen |
| mix-blend-overlay | Overlay |
| mix-blend-darken | Darken |
| mix-blend-lighten | Lighten |
| mix-blend-difference | Difference |
/* Tailwind 4: Define custom theme */
@import "tailwindcss";
@theme {
--color-primary: #6366f1;
--color-primary-light: #818cf8;
--color-primary-dark: #4f46e5;
--font-sans: "Inter", sans-serif;
}
/* Use in HTML */
<div class="bg-primary text-white">
Custom themed!
</div><!-- ── Border Width ── -->
<div class="border"> 1px solid (default)</div>
<div class="border-0"> No border</div>
<div class="border-2"> 2px solid</div>
<div class="border-4"> 4px solid</div>
<div class="border-8"> 8px solid</div>
<!-- ── Border Side ── -->
<div class="border-t"> Top only</div>
<div class="border-r"> Right only</div>
<div class="border-b"> Bottom only</div>
<div class="border-l"> Left only</div>
<div class="border-x"> Horizontal (left + right)</div>
<div class="border-y"> Vertical (top + bottom)</div>
<!-- ── Border Radius ── -->
<div class="rounded-none"> 0px</div>
<div class="rounded-sm"> 2px</div>
<div class="rounded"> 4px</div>
<div class="rounded-md"> 6px</div>
<div class="rounded-lg"> 8px</div>
<div class="rounded-xl"> 12px</div>
<div class="rounded-2xl"> 16px</div>
<div class="rounded-3xl"> 24px</div>
<div class="rounded-full"> 9999px (circle/pill)</div>
<!-- ── Ring (outline-style border) ── -->
<div class="ring-2 ring-blue-500"> 2px blue ring</div>
<div class="ring-4 ring-offset-2 ring-green-500">
Ring with offset
</div><!-- ── Box Shadows ── -->
<div class="shadow-sm"> Small shadow</div>
<div class="shadow"> Medium shadow</div>
<div class="shadow-md"> Medium-large</div>
<div class="shadow-lg"> Large shadow</div>
<div class="shadow-xl"> Extra large</div>
<div class="shadow-2xl"> Huge shadow</div>
<div class="shadow-none"> No shadow</div>
<!-- ── Colored Shadow ── -->
<div class="shadow-blue-500/50"> Blue shadow at 50%</div>
<div class="shadow-red-500/30"> Red shadow at 30%</div>
<!-- ── Opacity ── -->
<div class="opacity-0"> Fully transparent</div>
<div class="opacity-25"> 25%</div>
<div class="opacity-50"> 50%</div>
<div class="opacity-75"> 75%</div>
<div class="opacity-100"> Fully opaque (default)</div>
<!-- ── Transitions ── -->
<div class="transition"> All properties, 150ms</div>
<div class="transition-all duration-300"> All, 300ms</div>
<div class="transition-colors duration-200"> Color only, 200ms</div>
<div class="transition-transform duration-500"> Transform only</div>
<div class="transition-opacity duration-150"> Opacity only</div>
<div class="ease-linear"> Linear easing</div>
<div class="ease-in"> Ease in</div>
<div class="ease-out"> Ease out</div>
<div class="ease-in-out"> Ease in-out</div>| Class | CSS Transform |
|---|---|
| scale-0 | scale(0) |
| scale-50 | scale(0.5) |
| scale-75 | scale(0.75) |
| scale-100 | scale(1) |
| scale-105 | scale(1.05) |
| scale-110 | scale(1.1) |
| scale-125 | scale(1.25) |
| scale-150 | scale(1.5) |
| rotate-0 | rotate(0deg) |
| rotate-45 | rotate(45deg) |
| rotate-90 | rotate(90deg) |
| rotate-180 | rotate(180deg) |
| translate-x-4 | translateX(1rem) |
| translate-y-2 | translateY(0.5rem) |
| Class | CSS Filter |
|---|---|
| blur-none | blur(0) |
| blur-sm | blur(4px) |
| blur | blur(8px) |
| blur-md | blur(12px) |
| blur-lg | blur(16px) |
| blur-xl | blur(24px) |
| blur-2xl | blur(40px) |
| brightness-50 | brightness(0.5) |
| brightness-100 | brightness(1) |
| brightness-150 | brightness(1.5) |
| grayscale | grayscale(100%) |
| sepia | sepia(100%) |
| invert | invert(100%) |
<!-- ── Built-in Animations ── -->
<div class="animate-spin"> Rotate 360deg infinitely</div>
<div class="animate-ping"> Scale + opacity pulse</div>
<div class="animate-pulse"> Fade in/out pulse</div>
<div class="animate-bounce"> Bounce up and down</div>
<!-- ── Animation Duration ── -->
<div class="animate-pulse duration-1000"> 1s pulse</div>
<div class="animate-pulse duration-3000"> 3s pulse</div>
<!-- ── Animation Play State ── -->
<div class="animate-spin paused"> Paused</div>
<div class="animate-spin running"> Running (default)</div>
<!-- ── Custom Animation with Keyframes ── -->
<style>
@keyframes slide-in {
from { transform: translateX(-100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
</style>
<div class="animate-[slide-in_0.5s_ease-out]">
Custom slide-in animation
</div>/* ── Tailwind 4: Define animations in CSS ── */
@import "tailwindcss";
@theme {
--animate-fade-in: fade-in 0.3s ease-out;
--animate-slide-up: slide-up 0.5s ease-out;
--animate-scale-in: scale-in 0.2s ease-out;
}
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slide-up {
from { transform: translateY(20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
@keyframes scale-in {
from { transform: scale(0.9); opacity: 0; }
to { transform: scale(1); opacity: 1; }
}<!-- ── Button Hover Effects ── -->
<button class="bg-blue-600 hover:bg-blue-700
hover:shadow-lg hover:shadow-blue-500/25
hover:-translate-y-0.5
active:translate-y-0 active:shadow-md
transition-all duration-200">
Hover me
</button>
<!-- ── Card Hover ── -->
<div class="bg-white rounded-xl shadow-sm
hover:shadow-xl hover:-translate-y-1
transition-all duration-300">
<h3 class="text-lg font-semibold">Card Title</h3>
<p class="text-gray-600 mt-2">Description</p>
</div>
<!-- ── Image Zoom on Hover ── -->
<div class="overflow-hidden rounded-lg">
<img class="w-full h-64 object-cover
hover:scale-110 transition-transform duration-500" />
</div>
<!-- ── Dropdown Animation ── -->
<div class="group relative">
<button>Menu</button>
<div class="opacity-0 invisible group-hover:opacity-100
group-hover:visible group-hover:translate-y-0
translate-y-2 transition-all duration-200
absolute top-full mt-2">
Dropdown content
</div>
</div>| Class | Description |
|---|---|
| cursor-pointer | Pointer cursor |
| cursor-not-allowed | Disabled cursor |
| cursor-wait | Loading cursor |
| cursor-grab / cursor-grabbing | Drag cursor |
| select-none | No text selection |
| select-all | All selectable |
| pointer-events-none | Ignore pointer events |
| pointer-events-auto | Enable pointer events |
| resize-none | No resize |
| resize | Resizable (default) |
| Class | Description |
|---|---|
| invisible | visibility: hidden (keeps layout) |
| visible | visibility: visible |
| hidden | display: none (removes layout) |
| block | display: block |
| sr-only | Screen reader only (visually hidden) |
| not-sr-only | Undo sr-only |
| collapse | Collapse table rows/columns |
transition-all duration-200 ease-out for smooth hover effects. Combine with hover:-translate-y-1 for a lift effect and hover:shadow-lg for depth. Add active: variants for press-down feedback.Utility-first means applying single-purpose CSS classes directly in HTML instead of writing custom CSS rules. Benefits: faster development (no context-switching), consistent design system, smaller production CSS (PurgeCSS removes unused utilities), no class naming decisions, and easier responsive design with prefix variants. Trade-off: HTML can become verbose, but readability improves with consistent patterns.
Tailwind uses mobile-first responsive prefixes: sm: (640px+),md: (768px+), lg: (1024px+), xl:(1280px+), 2xl: (1536px+). Classes without a prefix apply to all screen sizes. Base styles are for mobile, and each breakpoint adds styles for larger screens. This means you design for mobile first, then layer on enhancements.
| Feature | Tailwind v3 | Tailwind v4 |
|---|---|---|
| Config | tailwind.config.js | CSS-native (@theme) |
| Engine | PostCSS plugin | Rust (Oxide, 10x faster) |
| Install | npm install + postcss config | @import "tailwindcss" |
| Variants | In config file | @custom-variant in CSS |
| Colors | In config theme | @theme --color-* |
| Content detection | content: [] array | Automatic detection |
| Container queries | Plugin needed | Built-in (@container) |
| CSS nesting | Plugin needed | Native support |
| 3rd party colors | Config extend | CSS import with @theme |
Tailwind is not ideal for: highly animated/complex CSS art, very content-heavy static sites (where a CMS controls styling), or teams deeply invested in a different design system. It also adds a learning curve for developers unfamiliar with utility classes. For heavily themed components with many state variations, consider combining Tailwind with CSS Modules or component libraries.
Three main approaches: (1) Extract React/Vue components with Tailwind classes applied directly. (2) Use @apply in CSS for frequently repeated patterns (but use sparingly). (3) Use the @theme directive in Tailwind 4 to define custom theme values. The preferred approach is component extraction — it keeps styling co-located with logic and enables TypeScript props for variants.