A media query is a conditional block of CSS that applies only when a stated condition about the viewport, device, or user preference is true. They are the mechanism underneath every “responsive” layout — the thing that makes a three-column grid collapse to one column on a phone, or a navigation bar swap for a hamburger menu below a certain width. The syntax is simple. Choosing where to put the breakpoints, and what unit to measure them in, is where most of the real difficulty lives.

Basic Syntax

A media query wraps a block of CSS in an @media rule with one or more conditions:

.sidebar {
  display: none;
}

@media (min-width: 768px) {
  .sidebar {
    display: block;
  }
}

Here, .sidebar is hidden by default and only becomes visible once the viewport is at least 768 pixels wide. Multiple conditions combine with and:

@media (min-width: 768px) and (max-width: 1023px) {
  /* applies only in this specific width range */
}

Mobile-First: min-width, Not max-width

There are two ways to structure breakpoints. Desktop-first starts with the full desktop layout as the default and uses max-width queries to override styles for smaller viewports. Mobile-first starts with the simplest, narrowest layout as the default and uses min-width queries to add complexity as the viewport grows.

/* Mobile-first: base styles are the narrow-viewport case */
.grid {
  display: block;
}

@media (min-width: 600px) {
  .grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1000px) {
  .grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

Mobile-first has become the dominant pattern, for a specific reason: mobile browsers generally do not need to download and discard styles meant for wider viewports (since those all live inside min-width blocks they never match), and the base styles represent the simplest, most constrained case, which is usually where design and content priorities are clearest anyway. Building up from that baseline tends to produce a more disciplined, better-prioritized layout than trimming down from a full desktop design.

Content-Based Breakpoints, Not Device-Based Ones

An early and persistent mistake is choosing breakpoints to match specific device widths — “the iPhone is 375px, the iPad is 768px, so those are my breakpoints.” This fails for a simple reason: there is no longer a small, stable set of device widths. Phones, tablets, foldables, and desktop windows come in a continuous range of sizes, and a breakpoint tuned to a 2019 device catalog is already wrong for whatever ships next year.

The more durable approach is to let the content decide where a layout breaks: resize the browser window gradually and watch for the point where a specific piece of content starts to look cramped, where line lengths get uncomfortably long, or where a grid starts to feel sparse — and put the breakpoint there, regardless of what device happens to be that width. This produces layouts that adapt gracefully across the actual range of viewport sizes people use, rather than layouts tuned to a handful of specific devices that will look wrong at every width in between.

Common Media Features Beyond Width

Width is the most common condition, but media queries support other features:

  • orientation: portrait / orientation: landscape — responds to the device’s rotation
  • prefers-color-scheme: dark / prefers-color-scheme: light — respects the user’s OS-level theme preference, the standard mechanism for offering a dark mode without a manual toggle
  • prefers-reduced-motion: reduce — respects a user’s OS setting requesting minimal animation, important for users with vestibular disorders triggered by motion
  • hover: hover / pointer: fine — detects whether the primary input can hover and has fine precision (a mouse) versus not (a touchscreen), useful for deciding whether hover-dependent interactions are appropriate
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

Should Breakpoints Use px, em, or rem?

This has been a genuinely contested question. px is the most literal and easiest to reason about directly. em and rem in a media query are calculated relative to the browser’s default font size (typically 16px, unless a user has changed their browser’s zoom or font-size preference) rather than relative to any element’s computed font size on the page — this distinction matters because it means em-based breakpoints respond to a user increasing their browser’s base font size (a common accessibility adjustment for low-vision users), triggering a layout change at a more generous effective viewport width for that user, while px-based breakpoints hold their pixel value regardless of the user’s font-size preference. Many accessibility-focused teams prefer em for this reason, though the practical difference is often small for a viewer using default browser settings.

Avoiding Breakpoint Sprawl

A stylesheet that accumulates a dozen or more distinct breakpoints, each hand-tuned to fix a specific component, becomes difficult to reason about and increasingly likely to have unintended interactions where two overlapping conditions both apply. The practical discipline: define a small set of shared breakpoint values (commonly three to five) as preprocessor variables or, where supported, native CSS custom properties, and reuse those same values across every component rather than picking a fresh number for each one:

$bp-tablet: 768px;
$bp-desktop: 1024px;
$bp-wide: 1440px;

@media (min-width: $bp-tablet) { /* ... */ }

This keeps the entire responsive system anchored to a handful of intentional decisions rather than dozens of accidental ones, and it makes future adjustments (say, shifting the tablet breakpoint by 16px) a one-line change instead of a codebase-wide search.

Testing Responsive Layouts Without Physical Devices

A browser’s built-in responsive design mode simulates a range of viewport dimensions instantly, without needing a drawer full of physical phones and tablets. It’s the right first pass for checking where a layout breaks — dragging the simulated viewport width slowly and watching for the exact pixel range where content starts to look cramped is a faster way to find a genuine content-based breakpoint than guessing at round numbers in advance. It has real limits, though: it simulates viewport size, not the actual mobile rendering engine, real touch behavior, or genuine device performance, so a layout that looks correct in simulated responsive mode should still be spot-checked on at least one or two real devices before being considered done.

Media Types: The Query That Predates Media Features

Before any of the feature-based queries above existed, CSS already had a coarser mechanism for conditional styles: the media type. @media print is the most useful surviving example — a block of styles that applies only when a page is being printed or previewed for printing, not when viewed on screen:

@media print {
  nav, aside, .no-print {
    display: none;
  }
  body {
    color: #000;
    font-size: 12pt;
  }
  a[href]::after {
    content: " (" attr(href) ")";
  }
}

Hiding navigation chrome, forcing black text on white background regardless of the screen theme, and printing a link’s actual URL next to its text (since a printed page can’t be clicked) are all standard print-stylesheet patterns. Media types and media features can combine in a single query — @media print and (min-width: 600px) is syntactically valid — though in practice print stylesheets are usually kept feature-independent, since print layout concerns (page breaks, ink economy, removing interactive chrome) are largely orthogonal to screen viewport width.

What Media Queries Don’t Do

A media query responds to the viewport’s dimensions, not to the dimensions of the specific component it’s applied to. A sidebar that has plenty of horizontal room inside a wide parent container, but happens to render on a narrow viewport, will still receive the narrow-viewport styles — even if the component itself has more space available than the viewport condition implies. This is a real limitation for building genuinely reusable, drop-anywhere components, and it’s the gap that eventually motivated container-level responsive techniques querying an element’s own size rather than the viewport’s.

Frequently Asked Questions

What’s the difference between mobile-first and desktop-first media queries?

Mobile-first defines the simplest, narrowest layout as the unconditional base style and uses min-width queries to add complexity as the viewport grows. Desktop-first defines the full desktop layout as the base and uses max-width queries to strip it down for smaller viewports. Mobile-first has become the more common pattern because it avoids loading styles meant only for wider viewports and tends to produce a more disciplined content hierarchy.

Should I use px, em, or rem for media query breakpoints?

All three work, but they behave differently: px is a fixed value regardless of user font-size settings, while em and rem in a media query scale with the browser’s base font size, meaning they adjust for a visitor who has increased their default font size for readability. Many accessibility-conscious teams prefer em, though the practical difference is small at a browser’s default settings.

How many breakpoints should a typical responsive site use?

There’s no fixed number, but a small, deliberately chosen set — commonly three to five shared values reused across every component — is far easier to maintain than breakpoints picked ad hoc per component. Store the values once (as variables) and reference them consistently rather than hardcoding a fresh pixel value in every media query.

Should breakpoints match specific device widths like the iPhone or iPad?

No. Device widths change constantly and a breakpoint tuned to a specific device catalog quickly becomes outdated. The more durable approach is to resize the viewport and find the point where the content itself starts to look cramped or sparse, and place the breakpoint there — a technique usually called content-based or “in-between” breakpoints.

What does prefers-reduced-motion do?

It’s a media feature that detects an OS-level accessibility setting requesting minimal animation, typically set by users with vestibular disorders who can experience discomfort from motion effects. Wrapping animation and transition durations in an @media (prefers-reduced-motion: reduce) block lets a site respect that preference without requiring a manual in-page toggle.