A media query applies a block of CSS only when a condition about the device or the viewport is true. That is the whole mechanism, and the interesting part is deciding what to condition on — because a breakpoint is not a device, it is a point where the layout stops working.
What is the syntax?
/* applies when the viewport is at least 48rem wide */
@media (min-width: 48rem) {
.layout {
grid-template-columns: 16rem 1fr;
}
}
/* applies when the viewport is narrower than that */
@media (max-width: 47.99rem) {
.layout {
grid-template-columns: 1fr;
}
}
Two things are worth noticing. The condition is about the viewport, not the device — a query does not know whether the page is open on a phone or in a narrow window on a large screen, and it should not care. And the unit is rem, which means the breakpoint scales with the reader's font size preference, so a reader who has set a larger default font gets the wider layout earlier.
Should I use min-width or max-width?
Use min-width, and always. It is the convention that makes the stylesheet scale up, and it avoids the overlap bug that comes with mixing the two.
the overlap bug
@media (max-width: 768px) { ... }
@media (min-width: 768px) { ... }
at exactly 768px, both apply — and the later one wins, by accident
the min-width convention
@media (min-width: 30rem) { ... }
@media (min-width: 48rem) { ... }
at 48rem, both apply — and both are meant to
With min-width queries, the cascade order does the work: a later query overrides an earlier one, so the widest query naturally wins. The base styles are the small-screen styles, and each query adds what is needed as the space grows.
What else can you query?
Width is the most common, but it is not the only thing that matters, and several of the others are worth more than width in practice.
/* the reader's motion preference */
@media (prefers-reduced-motion: reduce) {
.card { transition: none; }
}
/* the reader's colour scheme preference */
@media (prefers-color-scheme: dark) {
:root { --surface: #16161a; --text: #f2f2f2; }
}
/* printing */
@media print {
.sidebar { display: none; }
}
/* coarse pointer: a finger rather than a mouse */
@media (pointer: coarse) {
.icon-button { padding: 1rem; }
}
/* orientation */
@media (orientation: landscape) and (min-width: 48rem) {
.hero { grid-template-columns: 1fr 1fr; }
}
The preference queries are the ones that make a site feel considered. A reader who has asked their system to reduce motion should not get a page that slides elements in, and a reader who prefers dark mode should get one without having to toggle anything. Both are settings people go and change deliberately, and honouring them costs a handful of lines.
How do you combine conditions?
With the word and, and with commas for alternatives.
/* both must be true */
@media (min-width: 48rem) and (orientation: landscape) { ... }
/* either one is enough */
@media (min-width: 80rem), (prefers-contrast: more) { ... }
Two conditions that are often combined are width and orientation, and the combination is what makes a tablet in landscape get the desktop layout while a phone in landscape does not. A phone in landscape is wider than a small tablet in portrait, and width alone would give it the wrong layout.
What is a breakpoint, really?
It is the width at which your layout breaks, and the only way to find it is to look. A breakpoint that exists because a particular phone model is 390 pixels wide is a guess about a device. A breakpoint that exists because at 700 pixels the sidebar and the text no longer fit side by side is a fact about your design.
The practical approach is to build the layout with fluid and flexible pieces first — grid with auto-fit, flex with flex: 1, sizes in rem and percentages — so that there are fewer breakpoints to begin with. Then narrow the window until something actually looks wrong, and put the breakpoint there.
What are the prefers-* media features for?
Some media queries are about the screen, and some are about the person using it. The second kind starts with prefers-, and they are how you respect a setting the visitor has already made in their operating system.
prefers-reduced-motion is the important one. Some people get motion sickness from large animations, and the operating system lets them ask every site to reduce movement. The query lets you honour that without removing every effect from everyone.
.reveal {
opacity: 0;
transform: translateY(12px);
transition: opacity 400ms ease, transform 400ms ease;
}
.reveal.is-visible {
opacity: 1;
transform: none;
}
/* the animation still happens, but without the movement */
@media (prefers-reduced-motion: reduce) {
.reveal {
transform: none;
transition: opacity 200ms ease;
}
}Note that the transition is not removed - the fade is still there. Reduced motion means less movement, not less feedback, and a visitor who asked for calmer animations still deserves to see that something happened.
prefers-color-scheme is the other one you will meet constantly. It reports whether the operating system is set to a light or a dark theme, and it lets you define both palettes in one stylesheet.
:root {
--page-bg: #ffffff;
--page-text: #10243a;
}
@media (prefers-color-scheme: dark) {
:root {
--page-bg: #0d1826;
--page-text: #e8eef5;
}
}
body {
background: var(--page-bg);
color: var(--page-text);
}Two more are worth knowing about. prefers-contrast reports a request for more contrast, which is a good signal to strengthen borders and focus rings. And prefers-reduced-transparency reports a request to avoid blurred, translucent backgrounds - which is exactly what a glassmorphism effect ignores.
None of these queries need a breakpoint and none of them change the layout, so they are a safe place to start experimenting with media queries: nothing moves, and every visitor who has set the preference gets what they asked for.
Quick reference
- A media query applies CSS when a condition about the viewport or the device is true.
- Query the viewport, not the device — a narrow desktop window is still narrow.
- Use
min-widthand write the base styles for small screens. - Use
remfor breakpoints so they scale with the reader's font size. - Preference queries — motion, colour scheme, contrast — are worth more than width in many cases.
- Join conditions with
and, offer alternatives with a comma.
Try it yourself: add a preference query for reduced motion and one for dark mode to a page you have. Then resize the window slowly and note every width at which the layout stops looking right — those are your real breakpoints, and they are rarely the ones you would have guessed.