| Breakpoints |
|---|
| (base) | — | All widths; no media query is emitted. | Mobile-first default: write the phone layout unprefixed, then override at larger breakpoints. |
| sm | 640px | width ≥ 640px | Landscape phones and up. Written as a prefix on a utility: sm:flex. |
| md | 768px | width ≥ 768px | Tablets and up; the most common step for layout changes. |
| lg | 1024px | width ≥ 1024px | Laptops and up; where nav bars often expand and sidebars appear. |
| xl | 1280px | width ≥ 1280px | Desktops and up. |
| 2xl | 1536px | width ≥ 1536px | Large monitors; use sparingly, most layouts max out earlier. |
| max-sm | 640px | width < 640px | max-* variants flip a tier to a strict upper bound; use for phone-only styles. |
| max-md | 768px | width < 768px | Everything below tablet. |
| max-lg | 1024px | width < 1024px | Tablet-and-phone-only styles. |
| max-xl | 1280px | width < 1280px | Everything below full desktop width. |
| max-2xl | 1536px | width < 1536px | Nearly always equivalent to unprefixed; rarely worth using. |
| Patterns |
|---|
| flex-col md:flex-row | 768px | Stacked below 768px, side by side from 768px | The canonical mobile-first pair: one unprefixed base plus one override, no max-* needed. |
| grid-cols-1 md:grid-cols-3 | 768px | 1 column below 768px, 3 columns from 768px | Cards stack on phones and flow into a grid on tablet and up; pick a gap that works at both sizes. |
| hidden md:block | 768px | Hidden below 768px, visible from 768px | Ship desktop-only chrome past tablets; use md:hidden for the inverse. |
| sm:text-lg lg:text-2xl | 1024px | Both match at ≥ 1024px; lg wins | Min-width variants are emitted sorted ascending, so a larger breakpoint overrides a smaller one regardless of class order in the HTML. |
| max-lg:flex-col | 1024px | width < 1024px | Reach 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 ≥ 28rem | Shorthand 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–32rem | Container width ≥ 28rem and < 32rem | Explicit min/max bounds stack into a range — the between-window that viewport variants cannot express. |
| @max-md: | 28rem (448px) | Container width < 28rem | Apply styles below a container size; the container counterpart of max-*. |
| @container/main + @md/main: | 28rem (448px) | Container width ≥ 28rem, measured against the named container main | Named containers disambiguate which ancestor to measure when wrappers nest. |
| Gotchas |
|---|
| sm: | 40rem | Emits @media (width ≥ 40rem), not 640px | v4 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: | 768px | width ≥ 768px — and everything above it | There 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–1024px | width ≥ 768px and < 1024px | No range variant like md-lg: exists; stack a min and a max variant to build a window. |
| min-[475px]: | 475px | width ≥ 475px, one-off | Arbitrary 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: | 768px | At exactly 768px only md: matches | max-md is strictly width < 768px while md: is ≥, so the pair never overlaps and the old 767.98px max-width hack is unnecessary. |