Prefixes are mobile-first min-width media queries
sm: …
2xl: layers a style on top at that breakpoint and above.
Under the hood md:grid-cols-3 compiles to
@media (width >= 48rem) — a min-width query (v4 range syntax).
| prefix | min-width | compiled @media (v4 range syntax) |
|---|---|---|
sm: | 40rem (640px) | @media (width >= 40rem) |
md: | 48rem (768px) | @media (width >= 48rem) |
lg: | 64rem (1024px) | @media (width >= 64rem) |
xl: | 80rem (1280px) | @media (width >= 80rem) |
2xl: | 96rem (1536px) | @media (width >= 96rem) |
Resize the window: the grid below flips 1→3 columns at 768px, the text grows at 1024px. (768px == 48rem at the default 16px root font-size.)
Live: grid-cols-1 md:grid-cols-3 · text-sm lg:text-xl
cell 1
grid-cols-1 on mobile
cell 2
md:grid-cols-3 from 768px
cell 3
stacked → 3-across
grid display: — · columns: — · text font-size: —
Column count & font-size are VIEWPORT-DEPENDENT — shown live, never asserted by the gold-check (a narrow window is not a failure).
Dark mode (v4): prefers-color-scheme by default
dark: follows the OS setting via the
prefers-color-scheme media query. To drive it with a
.dark class instead, override the variant in CSS:
This demo applies that override, so the button toggles .dark on <html> and the panel responds — proof the class strategy works. (v3 did this with darkMode: 'class' in JS config; v4 is CSS-first.)
Dark-mode panel
bg-white dark:bg-slate-900 · text adapts too
Without the @custom-variant override, dark: would track the OS line above instead of the toggle.