CSS Media Queries Explained: Responsive Design Basics
CSS media queries apply styles conditionally based on viewport size, device features, and user preferences like color scheme or reduced motion.
A CSS media query applies a block of styles only when a condition about the browsing environment is true — the viewport is narrower than 600px, the device supports hover, or the user has asked for reduced motion. They’re the mechanism behind responsive design: one stylesheet that adapts to phones, tablets, desktops, and print, without separate pages for each.
The basic syntax
A media query pairs a media type with one or more feature checks, wrapped in an @media block:
@media (min-width: 768px) {
.sidebar {
display: block;
}
}
The media type (screen, print, all) is usually omitted since screen is the default context for most rules. Feature checks go in parentheses and can be combined with logical keywords:
and— both conditions must be true:(min-width: 768px) and (orientation: landscape),(comma) — acts asor:(min-width: 1200px), (orientation: landscape)not— negates the whole query:not all and (monochrome)
Range syntax ((width >= 768px)) is now widely supported as a more readable alternative to min-width/max-width pairs, mirroring how comparisons read in most programming languages.
Common layout features
width and height (plus their min-/max- variants) are the workhorses, used to define breakpoints. orientation: portrait | landscape reacts to aspect ratio rather than absolute size, which matters more on tablets than phones. hover and pointer (fine vs coarse) detect whether the primary input device can hover and how precise it is — useful for deciding whether a hover-revealed menu is a good idea, since a touchscreen has no hover state at all.
For layout that should respond to a container’s own size rather than the viewport — a card component reused in a narrow sidebar and a wide main column — container queries are the better tool. Media queries answer “how big is the screen”; container queries answer “how big is the box this component actually has.”
Preference-based media features
Beyond layout, media queries expose user preferences set at the OS or browser level:
prefers-color-scheme: dark | light— respects the user’s system theme, the mechanism behind CSS dark mode and thelight-dark()function.prefers-reduced-motion: reduce— signals that animations should be minimized or removed. Seeprefers-reduced-motionin depth for how to gate transitions and scroll effects behind it.prefers-contrast: more | less— requests higher or lower contrast than the default theme.prefers-reduced-data— a newer, less-supported signal that the user wants to conserve bandwidth, useful for gating autoplaying video or large background images.
These aren’t cosmetic extras. Treating prefers-reduced-motion as optional excludes users for whom motion causes real discomfort, and it costs nothing to respect.
Media queries vs container queries
| Media queries | Container queries | |
|---|---|---|
| Condition source | Viewport / device | A specific containing element |
| Good for | Page-level layout, print styles, user preferences | Reusable components used in varying contexts |
| Browser support | Universal, long-standing | Modern browsers only |
| Nesting behavior | Independent of DOM position | Requires container-type on an ancestor |
They’re complementary, not competing: page-level breakpoints and preference queries stay in @media; component-level responsiveness moves to @container. A common pattern combines both — a media query sets the page-level grid at a wide viewport, while a card inside one of that grid’s columns uses a container query to decide its own internal layout based on the column width it actually receives, which can differ from what the raw viewport width would suggest.
Mobile-first vs desktop-first authoring
Most modern CSS is written mobile-first: base styles target the smallest viewport, and min-width queries progressively add complexity as space increases.
.card {
display: block;
}
@media (min-width: 640px) {
.card {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
This tends to produce simpler cascades than desktop-first (max-width, subtracting complexity as space shrinks) because the base case is the simplest layout, and each query only adds rules rather than overriding a denser desktop layout piece by piece. It also pairs naturally with fluid units — clamp()-based type scales (see fluid typography with clamp()) can remove the need for a breakpoint entirely in cases where a smooth scale is enough.
Media queries beyond the screen
@media print remains genuinely useful for hiding navigation, ads, and interactive controls when a page is printed or exported to PDF, and for forcing link URLs to print alongside link text. It’s a small, often-forgotten corner of responsive design that costs little to support.
Media queries also interact with performance: the media attribute on a <link> tag can mark a stylesheet as non-render-blocking for conditions that don’t apply on load (e.g., a print stylesheet loaded with media="print"), which the browser deprioritizes without JavaScript. That’s a small but free win worth knowing about alongside broader tactics in the Core Web Vitals guide and responsive images with srcset/sizes, which solves the equivalent problem for image assets.
The takeaway
Media queries conditionally apply CSS based on viewport, device capability, or user preference, using @media blocks combined with and, ,, and not. Use viewport-based queries for page-level layout and preference queries (prefers-color-scheme, prefers-reduced-motion) unconditionally — they cost nothing and materially improve accessibility. Reach for container queries instead when the thing that needs to respond is a reusable component rather than the whole page.
Tagged
Keep reading
Takina · · 4 min read Container Query Units: cqw, cqh, and cqi Explained
Container query units like cqw and cqi size elements relative to their containing element, not the viewport — here's how and when to use them.
Takina · · 4 min read CSS Relative Color Syntax: Deriving Colors from Colors
Relative color syntax lets CSS derive a new color from an existing one by adjusting its channels directly, no preprocessor or JS required.
Takina · · 4 min read What Is CSS Subgrid? Nested Grid Alignment Explained
CSS subgrid lets a nested grid item inherit its parent's track sizing, so children can align to the same columns or rows across unrelated containers.