On this page
What is Tailwind CSS?
What is Tailwind CSS?
Tailwind CSS is a utility-first CSS framework that gives you low-level, single-purpose CSS classes — called utilities — and lets you compose them directly in your HTML to build any design without ever leaving your markup. Instead of writing .btn-primary { background: blue; padding: 8px 16px; ... } in a separate stylesheet, you write class="bg-blue-500 px-4 py-2 ..." directly on the element.
This is the core philosophy: style at the point of use. No context switching, no inventing class names, no stylesheet growing infinitely as the project scales.
The utility-first philosophy
Every CSS framework has an opinion about how to apply styles. Traditional frameworks like Bootstrap give you pre-built components: .btn, .card, .modal. You get a ready-made button quickly, but customizing it requires overriding specificity wars, and every project looks similar.
Tailwind takes the opposite approach. It gives you atomic building blocks:
bg-blue-500— setsbackground-colorto a specific shade of bluetext-white— setscolor: whitepx-4— sets horizontal padding to1rempy-2— sets vertical padding to0.5remrounded— setsborder-radius: 0.25remfont-semibold— setsfont-weight: 600hover:bg-blue-600— applies a darker background on hover
You compose these to build a button:
<button class="bg-blue-500 hover:bg-blue-600 text-white font-semibold px-4 py-2 rounded transition-colors">
Click me
</button>There are no components to override, no specificity problems. If you need a green button, you change bg-blue-500 to bg-green-500. Everything is explicit and local.
Why utility-first scales better
The paradox of traditional CSS is that it grows forever. Every new feature means new classes. Old classes are never deleted because you cannot be sure nothing uses them. After 12 months, stylesheets reach thousands of lines, and developers are afraid to change anything.
With Tailwind, your CSS file stops growing at some point. The utilities are finite — there are only so many colors, font sizes, and spacing values. Once your project uses most of them, the build output reaches a ceiling and stays there. Unused utilities are never included in the final build.
This is enabled by Tailwind's content scanning: the framework scans your HTML, JavaScript, and template files for class names and only generates CSS for the utilities you actually use. A typical production build is 5–15 KB of CSS, regardless of project size.
Tailwind v4 vs v3: what changed
Tailwind CSS v4 is a complete ground-up rewrite. The changes are significant:
The Oxide engine
Tailwind v4 replaces the pure-JavaScript PostCSS pipeline with Oxide, a hybrid engine written in Rust (using Lightning CSS) and JavaScript. Lightning CSS handles parsing, transforming, and bundling CSS at native speeds. The result is:
- Full build times reduced by ~5× on cold builds
- Incremental builds are near-instant — under 2ms on typical projects
- Automatic vendor prefixes without a separate autoprefixer plugin
- Modern CSS features like nesting, custom media queries, and
color-mix()work out of the box
CSS-first configuration
In v3, configuration lived in tailwind.config.js — a JavaScript file where you defined colors, fonts, breakpoints, and plugins. In v4, the configuration moves entirely into your CSS file:
/* tailwind.css */
@import "tailwindcss";
@theme {
--color-brand: #6366f1;
--font-display: "Inter", sans-serif;
--breakpoint-xs: 480px;
}The @theme directive registers custom design tokens that generate utility classes automatically. Defining --color-brand: #6366f1 makes bg-brand, text-brand, and border-brand available immediately.
No more `tailwind.config.js`
In v4, there is no tailwind.config.js by default. The @theme block replaces theme.extend. The @source directive replaces content. The @variant directive replaces plugins for custom pseudo-class variants.
This means your entire Tailwind setup — imports, custom tokens, variant definitions — lives in one CSS file. The framework becomes a CSS library first, with JavaScript tooling as a secondary concern.
Other v4 changes
- New color palette — the default palette was updated and all opacity utilities now use CSS
color-mix()instead of CSS variables tricks. - P3 color support — Tailwind v4 ships with OKLCH-based colors that work in wide-gamut displays.
- Simplified breakpoints — breakpoints are plain CSS custom properties.
@starting-stylesupport — entry animations on newly inserted DOM elements.- Container queries built-in via
@containerand@min-*/@max-*utilities.
The Tailwind ecosystem
Tailwind is not just a CSS file. It comes with a rich ecosystem:
| Tool | Purpose |
|---|---|
@tailwindcss/vite |
Vite plugin — recommended for most projects |
@tailwindcss/cli |
Standalone CLI for non-Vite workflows |
@tailwindcss/postcss |
PostCSS plugin for webpack, Parcel, etc. |
@tailwindcss/typography |
The prose plugin for rich text content |
@tailwindcss/forms |
Resets and base styles for form elements |
| Tailwind UI | Premium component library |
| Headless UI | Unstyled, accessible components |
The VS Code extension Tailwind CSS IntelliSense (by Tailwind Labs) is essential. It provides autocomplete for every class, documentation on hover, and linting for invalid class names. Install it before writing a single line of Tailwind code.
When to use Tailwind
Tailwind is an excellent fit for:
- Custom designs where Bootstrap or Material UI components would need heavy overriding
- Large teams where CSS naming conventions are difficult to enforce
- Component-based frameworks like React, Vue, Angular, and Svelte — each component owns its styles via classes
- Design system implementations where a fixed token set maps 1:1 to utility classes
Tailwind is a poor fit for:
- Unstyled HTML documents you do not control (e.g., user-generated content) — use the
typographyplugin - Tiny prototypes where a reset + a few custom rules are enough
- Projects where team members strongly prefer CSS modules or BEM
Practice
- Open play.tailwindcss.com and recreate the card from the code example above using only utility classes. Try changing the background color and padding.
- Add
hover:shadow-xlto the card and observe how the hover state is applied inline. - Compare the generated CSS output (bottom panel) with the traditional stylesheet equivalent. Notice that only the used utilities appear in the output.
<!-- Traditional CSS approach: write classes, then style them separately -->
<style>
.card {
background: white;
border-radius: 8px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
.card-title {
font-size: 1.25rem;
font-weight: 700;
color: #111;
margin-bottom: 8px;
}
.card-text {
color: #555;
line-height: 1.6;
}
</style>
<div class="card">
<h2 class="card-title">Hello, world</h2>
<p class="card-text">This is a card component.</p>
</div>
Sign in to track your progress