Skip to content

Tailwind Breakpoints Explained

Tailwind's responsive breakpoints as reference rows: the sm-to-2xl min-width tiers, the max-* variants, mobile-first patterns, container queries, and the gotchas around rem, ranges, and arbitrary values.

Tailwind's five viewport breakpoints are min-width tiers: an sm: utility applies from 640px all the way up, so every layout starts mobile-first and grows. The max-* variants flip each tier to a strict upper bound, and the @container family reuses the same idea against a parent's width instead of the viewport. This table maps each variant to its exact query, plus the common patterns and the gotchas.

Reference table · 26 entries
26 of 26 rows
Breakpoints
(base)—All widths; no media query is emitted.Mobile-first default: write the phone layout unprefixed, then override at larger breakpoints.
sm640pxwidth ≥ 640pxLandscape phones and up. Written as a prefix on a utility: sm:flex.
md768pxwidth ≥ 768pxTablets and up; the most common step for layout changes.
lg1024pxwidth ≥ 1024pxLaptops and up; where nav bars often expand and sidebars appear.
xl1280pxwidth ≥ 1280pxDesktops and up.
2xl1536pxwidth ≥ 1536pxLarge monitors; use sparingly, most layouts max out earlier.
max-sm640pxwidth < 640pxmax-* variants flip a tier to a strict upper bound; use for phone-only styles.
max-md768pxwidth < 768pxEverything below tablet.
max-lg1024pxwidth < 1024pxTablet-and-phone-only styles.
max-xl1280pxwidth < 1280pxEverything below full desktop width.
max-2xl1536pxwidth < 1536pxNearly always equivalent to unprefixed; rarely worth using.
Patterns
flex-col md:flex-row768pxStacked below 768px, side by side from 768pxThe canonical mobile-first pair: one unprefixed base plus one override, no max-* needed.
grid-cols-1 md:grid-cols-3768px1 column below 768px, 3 columns from 768pxCards stack on phones and flow into a grid on tablet and up; pick a gap that works at both sizes.
hidden md:block768pxHidden below 768px, visible from 768pxShip desktop-only chrome past tablets; use md:hidden for the inverse.
sm:text-lg lg:text-2xl1024pxBoth match at ≥ 1024px; lg winsMin-width variants are emitted sorted ascending, so a larger breakpoint overrides a smaller one regardless of class order in the HTML.
max-lg:flex-col1024pxwidth < 1024pxReach for max-* only when the small-screen case is the exception; mixing both directions on one property gets confusing fast.
Container queries
@container—Marks this element as the container its descendants measure.Add it to a card or sidebar wrapper; @ variants inside then resolve against that box instead of the viewport.
@md:28rem (448px)Container width ≥ 28remShorthand for @min-md:. Container queries are mobile-first too, and the scale is its own (@sm 24rem, @md 28rem, @lg 32rem, @xl 36rem…) — not the 640/768/1024 viewport scale.
@min-md:@max-lg:28–32remContainer width ≥ 28rem and < 32remExplicit min/max bounds stack into a range — the between-window that viewport variants cannot express.
@max-md:28rem (448px)Container width < 28remApply styles below a container size; the container counterpart of max-*.
@container/main + @md/main:28rem (448px)Container width ≥ 28rem, measured against the named container mainNamed containers disambiguate which ancestor to measure when wrappers nest.
Gotchas
sm:40remEmits @media (width ≥ 40rem), not 640pxv4 defines breakpoints in rem (--breakpoint-sm: 40rem). At the default 16px root that is 640px. Media-query rem keys off the initial root size, so your html { font-size } never shifts breakpoints — but a user's browser text-size preference does.
md:768pxwidth ≥ 768px — and everything above itThere is no desktop-first tier: an sm: or md: style keeps applying at larger sizes. Override at a bigger breakpoint instead of un-setting at a smaller one.
md:max-lg:768–1024pxwidth ≥ 768px and < 1024pxNo range variant like md-lg: exists; stack a min and a max variant to build a window.
min-[475px]:475pxwidth ≥ 475px, one-offArbitrary breakpoints work inline, but a magic number does not read as a tier. Prefer registering --breakpoint-3xl: 120rem in @theme so the name and sort order stay consistent.
md: + max-md:768pxAt exactly 768px only md: matchesmax-md is strictly width < 768px while md: is ≥, so the pair never overlaps and the old 767.98px max-width hack is unnecessary.