Responsive Tailwind is just putting a prefix in front of a class. You never write a media query.
<!-- stacked on phones, side by side at 768px and up -->
<div class="flex flex-col md:flex-row gap-4">
<div>1</div>
<div>2</div>
</div>md:flex-row means “flex-direction: row only at 768px and up.” In plain CSS:
.box {
display: flex;
flex-direction: column;
gap: 1rem;
}
@media (min-width: 768px) {
.box {
flex-direction: row;
}
}The same thing, in one line of HTML.
TipsHow to choose your breakpointsHow to choose breakpoints in the first place, in this quick referenceThe five prefixes
Tailwind ships five dividing lines.
| Prefix | Takes effect from | Intended for |
|---|---|---|
| (none) | Every width | Phones (the base) |
sm: | 640px and up | Larger phones |
md: | 768px and up | Tablets |
lg: | 1024px and up | Desktop |
xl: | 1280px and up | Large screens |
2xl: | 1536px and up | Extra large |
In practice you’ll use md: and lg:. “Two columns from tablet, three from desktop” needs only those two.
<!-- one column on phones → two on tablet → three on desktop -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div class="p-4 bg-white rounded-xl">1</div>
<div class="p-4 bg-white rounded-xl">2</div>
<div class="p-4 bg-white rounded-xl">3</div>
</div>Read left to right, narrow to wide—that’s how responsive Tailwind reads.
Prefixes are always “and up”
This is Tailwind’s biggest design decision. Every prefix is min-width—“at this width and up.” There is no other direction.
Which fixes the way you write:
- No prefix = the phone look (the base)
- Prefix = an override for wider screens
In other words mobile-first is enforced. There’s no room to wonder “should I write this with max-width?”
Showing and hiding
“Hamburger on phones, a row of links on desktop”—the classic—is prefixes alone.
<!-- only appears on phones -->
<button class="md:hidden">Menu</button>
<!-- only appears on desktop -->
<nav class="hidden md:flex gap-4">
<a href="#">Home</a>
<a href="#">About</a>
</nav>Read them as:
md:hidden—visible normally, hidden at 768px and uphidden md:flex—hidden normally,display: flexat 768px and up
hidden is display: none. It’s md:flex rather than md:block because we want that nav laid out in a row. Being able to say how it appears is what’s nice about this form.
Switching type sizes and spacing too
A heading at the same size on phones and desktop always looks wrong on one of them.
<h1 class="text-2xl md:text-4xl font-bold">
Shima's page
</h1>24px on phones, 36px at 768px and up. Spacing switches the same way.
<section class="px-4 py-8 md:px-8 md:py-16">
...
</section>Four combinations you’ll reuse
Stacked on phones, row on desktop
<div class="flex flex-col md:flex-row gap-4">More columns as the screen grows
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">Full width on phones, fixed sidebar on desktop
<aside class="w-full md:w-60 md:shrink-0">Capped content width (centred at any size)
<div class="max-w-4xl mx-auto px-4 md:px-8">That last one only has a prefix on the padding. max-w-4xl mx-auto works at every width and shrinks on its own when the screen is narrow, so no switching is needed. Preferring forms that don’t need switching at all is the same instinct as in plain CSS.
Keeping long class lists readable
As prefixes multiply, the lists get long. The trick to keeping them readable is fixing the order.
<!-- recommended: group narrow-screen first, then wider -->
<div class="grid grid-cols-1 gap-4 p-4 md:grid-cols-2 md:gap-6 md:p-8 lg:grid-cols-3">All the unprefixed ones first, then all the md:, then lg:. Just sorting them this way makes them far easier to read. There are tools that reorder automatically, but doing it deliberately by hand is plenty to start.
Summary of this lesson
- Put
md:in front of a class and it means “at this width and up” - Every prefix is
min-width—which is why mobile-first is enforced - No prefix = phone, prefix = wider. Read left to right, narrow to wide
- Mistaking
md:for “phones” inverts your show/hide logic - You’ll use
md:andlg:. Prefer forms that need no switching at all
Next: the hover: and focus: prefixes that react to state. The mechanism is identical to md:.