Learn Tailwind CSS utility-first styling, layout with Flexbox and Grid, responsive and state variants, dark mode, design tokens, component patterns, and how to keep markup maintainable.
What Is Tailwind CSS?
Tailwind CSS is a utility-first CSS framework. Instead of writing a new class for every design, you compose small single-purpose classes such as p-4, text-lg, rounded-xl, and flex directly in your markup.
Why developers choose it
- Speed: you style in the HTML without switching files or inventing class names.
- Consistency: spacing, colors, and sizes come from a shared design scale.
- Small CSS output: only the classes you actually use are generated.
- Responsive and state variants built in:
md:,hover:,dark:and more.
Trade-offs to know
- Long class lists can look noisy; extract components to keep them readable.
- You still need to understand core CSS: the box model, Flexbox, Grid, and the cascade.
- Setup differs between major versions, so follow the official guide for the version you install.
Plain CSS versus Tailwind utilities
<!-- Plain CSS: write a class, then write the CSS in another file -->
<button class="primary-button">Save</button>
<!-- Tailwind: style directly with utilities -->
<button class="rounded-lg bg-blue-600 px-4 py-2 font-semibold text-white hover:bg-blue-700">
Save
</button>Installing and Configuring Tailwind
The exact steps depend on your Tailwind version and build tool, so always follow the current official installation guide rather than mixing instructions from different major versions. The example below shows the general shape of a Vite-based setup with Tailwind v4.
Installing Tailwind with Vite (v4 style)
npm create vite@latest my-app -- --template vanilla
cd my-app
npm install tailwindcss @tailwindcss/vitevite.config.js
import { defineConfig } from "vite";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
plugins: [tailwindcss()],
});src/style.css
@import "tailwindcss";Utility-First Styling Basics
Each utility class represents one style decision. Learning the naming pattern is most of the work.
- Spacing:
p-4(padding),px-6(horizontal),mt-2(margin top),gap-4,space-y-3. - Sizing:
w-full,w-64,max-w-md,h-48,min-h-screen. - Typography:
text-sm,text-2xl,font-bold,leading-7,tracking-wide,text-center. - Colors:
bg-slate-100,text-slate-700,border-slate-200,bg-blue-600. - Borders and effects:
rounded-xl,border,shadow-sm,ring-2,opacity-80. - The spacing scale is multiples of a base unit;
p-4is 1rem with the default theme.
A styled article card from utilities
<article class="max-w-md rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
<p class="text-sm font-semibold uppercase tracking-wide text-blue-700">Tutorial</p>
<h2 class="mt-2 text-2xl font-bold text-slate-900">Learn Tailwind CSS</h2>
<p class="mt-3 leading-7 text-slate-600">
Compose small utilities to build any design without leaving your HTML.
</p>
</article>Layout with Flexbox and Grid Utilities
flex,flex-col,items-center,justify-between,gap-4map directly to Flexbox properties.grid,grid-cols-3,col-span-2,gap-6build Grid layouts.container,mx-auto, andmax-w-*center and constrain page width.hidden,block, andinline-flexcontrol display.
A navbar and a three-column grid
<header class="border-b border-slate-200 bg-white">
<nav class="mx-auto flex max-w-6xl items-center justify-between px-4 py-3">
<a href="/" class="text-lg font-bold text-slate-900">DevNotes</a>
<ul class="flex items-center gap-6 text-sm font-medium text-slate-600">
<li><a class="hover:text-slate-900" href="/docs">Docs</a></li>
<li><a class="hover:text-slate-900" href="/blog">Blog</a></li>
<li><a class="rounded-lg bg-blue-600 px-3 py-1.5 text-white hover:bg-blue-700" href="/signup">Sign up</a></li>
</ul>
</nav>
</header>
<section class="mx-auto grid max-w-6xl gap-6 px-4 py-10 sm:grid-cols-2 lg:grid-cols-3">
<div class="rounded-xl bg-slate-100 p-6">One</div>
<div class="rounded-xl bg-slate-100 p-6">Two</div>
<div class="rounded-xl bg-slate-100 p-6">Three</div>
</section>Responsive and State Variants
Prefix a utility with a variant to apply it only in a certain condition.
Responsive prefixes (mobile first)
- Unprefixed utilities apply at all sizes, starting with the smallest screens.
sm:,md:,lg:,xl:apply from that breakpoint upward.- Example:
text-base md:text-lg lg:text-xlgrows the text as the screen widens.
State and condition prefixes
hover:,focus:,focus-visible:,active:,disabled:for interaction states.group-hover:andpeer-checked:style an element based on a parent or sibling.first:,last:,odd:,even:for position.dark:for dark mode andmotion-reduce:for reduced-motion users.
Variants for responsive, hover, focus, and disabled states
<button
class="w-full rounded-lg bg-blue-600 px-4 py-2 font-semibold text-white
hover:bg-blue-700
focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600
disabled:cursor-not-allowed disabled:opacity-50
sm:w-auto"
>
Continue
</button>
<a href="#" class="group flex items-center gap-2">
<span>Read more</span>
<svg class="h-4 w-4 transition-transform group-hover:translate-x-1" viewBox="0 0 16 16" aria-hidden="true">
<path d="M3 8h10M9 4l4 4-4 4" fill="none" stroke="currentColor" stroke-width="2"/>
</svg>
</a>Dark Mode
Use the dark: variant to define dark styles next to the light ones. By default it follows the operating system preference.
A card that supports light and dark themes
<div class="rounded-2xl border border-slate-200 bg-white p-6 text-slate-700
dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300">
<h3 class="text-lg font-semibold text-slate-900 dark:text-white">Dark mode ready</h3>
<p class="mt-2">This card adapts to the user's color scheme.</p>
</div>Customizing Your Design System
You can extend the theme with your own colors, fonts, and spacing so the utilities reflect your brand.
Defining theme tokens in Tailwind v4
@import "tailwindcss";
@theme {
--color-brand: #2457d6;
--color-brand-dark: #1b43a8;
--font-display: "Inter", system-ui, sans-serif;
--breakpoint-3xl: 120rem;
}
/* Now available as: bg-brand, text-brand-dark, font-display, 3xl:... */Arbitrary values
When you need a one-off value, use square brackets instead of editing the theme.
Arbitrary values for one-offs
<div class="w-[22rem] bg-[#f5f7fb] top-[117px] grid-cols-[200px_1fr]">
...
</div>Reusable Components and Avoiding Repetition
Utility-first does not mean copy-pasting long class lists. Repeated UI should become a component.
- In React, Vue, Svelte, or a template engine, wrap repeated markup in a component with props.
- In plain HTML projects, use partials or includes from your static site generator.
- Use
@applysparingly for small shared patterns; components are usually a better abstraction. - A Prettier plugin can sort classes into a consistent order automatically.
A reusable React button component
// Button.jsx
const styles = {
primary: "bg-blue-600 text-white hover:bg-blue-700",
secondary: "bg-slate-100 text-slate-900 hover:bg-slate-200",
};
export function Button({ variant = "primary", children, ...props }) {
return (
<button
className={`rounded-lg px-4 py-2 font-semibold focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ${styles[variant]}`}
{...props}
>
{children}
</button>
);
}Accessibility with Tailwind
- Keep visible focus styles with
focus-visible:utilities. - Use
sr-onlyto provide text for screen readers only. - Choose color combinations with enough contrast.
- Respect motion preferences with
motion-reduce:. - Use semantic HTML elements underneath your utility classes.
Screen-reader text and reduced motion
<button type="button" class="rounded-full p-2 hover:bg-slate-100 focus-visible:outline focus-visible:outline-2">
<svg class="h-5 w-5" aria-hidden="true" viewBox="0 0 20 20"><path d="M5 5l10 10M15 5L5 15" stroke="currentColor" stroke-width="2"/></svg>
<span class="sr-only">Close menu</span>
</button>
<div class="animate-spin motion-reduce:animate-none h-6 w-6 rounded-full border-2 border-blue-600 border-t-transparent"></div>Best Practices
- Learn the underlying CSS first; Tailwind is a faster way to write it, not a replacement.
- Design mobile first and add
sm:,md:,lg:overrides as needed. - Extract components when a pattern appears three or more times.
- Stick to the design scale and avoid scattering arbitrary values.
- Keep markup semantic and accessible.
- Use editor extensions for autocomplete and class sorting.
Complete Example: Pricing Card
This example assumes Tailwind is already installed and configured in the project.
Responsive pricing card with dark mode
<section class="mx-auto max-w-5xl px-4 py-12">
<div class="grid gap-6 md:grid-cols-2">
<article class="rounded-2xl border border-slate-200 bg-white p-8 shadow-sm dark:border-slate-700 dark:bg-slate-900">
<h3 class="text-lg font-semibold text-slate-900 dark:text-white">Starter</h3>
<p class="mt-4 flex items-baseline gap-1">
<span class="text-4xl font-bold text-slate-900 dark:text-white">$9</span>
<span class="text-slate-500">/month</span>
</p>
<ul class="mt-6 space-y-3 text-slate-600 dark:text-slate-300">
<li class="flex gap-2"><span aria-hidden="true">✓</span> 3 projects</li>
<li class="flex gap-2"><span aria-hidden="true">✓</span> Community support</li>
</ul>
<a href="/signup?plan=starter"
class="mt-8 block rounded-lg bg-slate-900 px-4 py-2 text-center font-semibold text-white
hover:bg-slate-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2">
Choose Starter
</a>
</article>
<article class="rounded-2xl border-2 border-blue-600 bg-white p-8 shadow-md dark:bg-slate-900">
<p class="text-xs font-semibold uppercase tracking-wide text-blue-700 dark:text-blue-400">Most popular</p>
<h3 class="mt-1 text-lg font-semibold text-slate-900 dark:text-white">Pro</h3>
<p class="mt-4 flex items-baseline gap-1">
<span class="text-4xl font-bold text-slate-900 dark:text-white">$29</span>
<span class="text-slate-500">/month</span>
</p>
<ul class="mt-6 space-y-3 text-slate-600 dark:text-slate-300">
<li class="flex gap-2"><span aria-hidden="true">✓</span> Unlimited projects</li>
<li class="flex gap-2"><span aria-hidden="true">✓</span> Priority support</li>
</ul>
<a href="/signup?plan=pro"
class="mt-8 block rounded-lg bg-blue-600 px-4 py-2 text-center font-semibold text-white
hover:bg-blue-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2">
Choose Pro
</a>
</article>
</div>
</section>Frequently Asked Questions
Is Tailwind a replacement for CSS?
No. Tailwind generates CSS utilities and is a different way to author styles. Understanding core CSS still helps a lot.
Do Tailwind classes work without setup?
Not automatically in every project. You need the appropriate stylesheet and build setup for the Tailwind version you use.
Can I create reusable designs in Tailwind?
Yes. Reuse components, templates, and design tokens rather than repeating large blocks of markup everywhere.
Does Tailwind make my CSS file huge?
No. Tailwind generates only the utilities it finds in your source files, so production CSS is usually small.
How do I add custom colors or fonts?
Define them as theme tokens in your Tailwind configuration for your version, then use the generated utilities such as bg-brand or font-display.
Is Tailwind good for beginners?
It can be, especially alongside learning CSS fundamentals. Beginners should understand Flexbox, Grid, and the box model so the utility names make sense.