hover:
Mouse over the element. The most common interactive state.
Tailwind CSS is a utility-first CSS framework. Instead of writing custom CSS, you compose styles from small, single-purpose classes directly in your markup. This guide explains the core concepts with interactive demos you can play with.
Traditional CSS requires naming things and writing rules in a separate file:
.card { padding: 1rem; border-radius: 0.5rem; background-color: #3b82f6; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);}With Tailwind, you express the same thing inline:
<div class="p-4 rounded-lg bg-blue-500 shadow-md">...</div>Every class maps to exactly one CSS property. p-4 is padding: 1rem. rounded-lg is border-radius: 0.5rem. No naming, no context switching, no dead CSS.
Here is that exact card, built with Tailwind classes right inside this MDX file:
This is a Tailwind card written directly in MDX using utility classes. No custom CSS file needed — just bg-gradient-to-r, rounded-xl, shadow-lg, and friends.
Tailwind makes flexbox intuitive. The class names mirror the CSS properties:
| Tailwind Class | CSS Property |
|---|---|
flex | display: flex |
flex-row | flex-direction: row |
flex-col | flex-direction: column |
justify-center | justify-content: center |
items-center | align-items: center |
gap-4 | gap: 1rem |
CSS Grid in Tailwind is just as composable. The key classes are:
| Tailwind Class | CSS Property |
|---|---|
grid | display: grid |
grid-cols-3 | grid-template-columns: repeat(3, 1fr) |
col-span-2 | grid-column: span 2 |
gap-4 | gap: 1rem |
Tailwind uses mobile-first breakpoint prefixes. Unprefixed classes apply at all sizes. Prefixed classes apply at that breakpoint and above.
| Prefix | Min Width | Common Use |
|---|---|---|
| (none) | 0px | Mobile default |
sm: | 640px | Large phones, small tablets |
md: | 768px | Tablets |
lg: | 1024px | Laptops |
xl: | 1280px | Desktops |
A responsive grid looks like this:
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4"></div>This means: 1 column on mobile, 2 on small screens, 4 on large screens. No media queries to write.
MDX supports raw HTML directly, so you can apply Tailwind classes with plain <div> tags:
Green Card
Purple Card
Heads up — This is a custom callout built entirely with Tailwind utilities: border-l-4, border-amber-400, bg-amber-50, and dark:bg-amber-950 for dark mode support.
Gradients, shadows, and rounded corners — all composed from single-purpose classes. This card uses bg-gradient-to-br, from-pink-500, via-red-500, to-orange-500, shadow-xl, and rounded-xl.
The MDX source for the colored cards above is just:
<div class="grid grid-cols-1 sm:grid-cols-3 gap-4"> <div class="rounded-lg bg-blue-500 p-4 text-white text-center font-bold shadow-md">Blue Card</div>
...</div>Tailwind uses a consistent spacing scale based on 0.25rem (4px) increments:
| Class | Value | Pixels |
|---|---|---|
p-0 | 0 | 0px |
p-1 | 0.25rem | 4px |
p-2 | 0.5rem | 8px |
p-4 | 1rem | 16px |
p-6 | 1.5rem | 24px |
p-8 | 2rem | 32px |
This scale applies to padding (p-), margin (m-), gap (gap-), width (w-), height (h-), and more. The consistency means your spacing always looks intentional.
Tailwind ships with a curated color palette. Each color has shades from 50 (lightest) to 950 (darkest):
<div class="bg-blue-500 text-white">Default blue</div><div class="bg-blue-100 text-blue-900">Light blue surface</div><div class="border border-blue-300">Blue border</div>The pattern is always {property}-{color}-{shade}:
bg- for backgroundtext- for text colorborder- for border colorring- for focus ringsYou can also use opacity modifiers: bg-blue-500/50 gives blue at 50% opacity.
Tailwind handles hover, focus, and other states with prefixes — just like responsive breakpoints:
<button class="bg-blue-500 hover:bg-blue-600 active:bg-blue-700 focus:ring-2 focus:ring-blue-300 disabled:opacity-50 disabled:cursor-not-allowed"> Click me</button>Common state prefixes:
hover:
Mouse over the element. The most common interactive state.
focus:
Element has keyboard or click focus. Essential for accessibility.
active:
Element is being pressed/clicked. Brief visual feedback.
disabled:
Element is disabled. Typically reduces opacity and changes cursor.
No naming
You never waste time inventing class names like .card-wrapper-inner-header. The utilities
describe what they do.
No dead CSS
Unused classes are automatically removed at build time. Your CSS only contains what you actually use.
Local reasoning
You can understand an element’s styles by reading its classes. No jumping between files or tracing specificity.
Safe changes
Changing a class only affects that element. No cascading side effects, no “I changed this and broke something else.”