Problem Solved

CSS · media queries

Home › Courses › CSS › Problems › Media queries
🎨 Concept · 3 min read

How do media queries work?
Breakpoints, min-width, mobile-first.

A media query applies CSS only when a condition is true — usually a viewport width. Write base styles for the smallest screen, then add rules for larger screens with min-width. That's mobile-first CSS, and it's the modern default. This page covers the syntax, the breakpoints that matter, and the difference between min-width and max-width.

Short answer: Use @media (min-width: 768px) {'{ ... }'} for mobile-first. Write base CSS for mobile, then add rules at each breakpoint. Common breakpoints: 640px, 768px, 1024px, 1280px, 1536px. Pick breakpoints where your design breaks, not where devices happen to be. Use max-width only if you're maintaining a desktop-first codebase. Prefer min-width for new projects — it's easier to reason about and produces smaller CSS.

✅ The two directions

min-width or max-width. Pick one per project.

min-width — mobile-first

Matches viewports at least this wide. Base styles are mobile. Add rules as the screen grows. Preferred.

max-width — desktop-first

Matches viewports at most this wide. Base styles are desktop. Override as the screen shrinks. Older pattern.

Why mobile-first wins

Smaller CSS (mobile users don't download desktop rules). Logical progression (add complexity, don't override). Easier to test (start with the hardest constraint).

Combining conditions

@media (min-width: 768px) and (max-width: 1023px) — matches only a specific range. Useful for "tablet-only" rules.

✅ Before and after

Mobile-first CSS in practice.

mobile-first.css
/* Base styles — mobile */
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
padding: 1rem;
}

.title {
font-size: 1.5rem;
}

/* Tablet — 768px and up */
@media (min-width: 768px) {
.grid {
grid-template-columns: 1fr 1fr;
padding: 2rem;
}
.title {
font-size: 2rem;
}
}

/* Desktop — 1024px and up /
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
.title {
font-size: 2.5rem;
}
}
Rendered layout:

Mobile (0–767px):
┌──────┐
│ Card │
├──────┤
│ Card │
├──────┤
│ Card │
└──────┘
font-size: 1.5rem

Tablet (768–1023px):
┌──────┬──────┐
│ Card │ Card │
├──────┼──────┤
│ Card │ │
└──────┴──────┘
font-size: 2rem

Desktop (1024px+):
┌──────┬──────┬──────┐
│ Card │ Card │ Card │
└──────┴──────┴──────┘
font-size: 2.5rem

✅ Base styles apply everywhere.
✅ Each min-width adds more columns.
✅ No "undo" rules — the CSS only grows.
✅ Smaller payload for mobile users.
desktop-first.css
/* Base styles — desktop */
.grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
padding: 2rem;
}

.title {
font-size: 2.5rem;
}

/* Tablet and below */
@media (max-width: 1023px) {
.grid {
grid-template-columns: 1fr 1fr;
padding: 2rem;
}
.title {
font-size: 2rem;
}
}

/* Mobile and below /
@media (max-width: 767px) {
.grid {
grid-template-columns: 1fr;
padding: 1rem;
}
.title {
font-size: 1.5rem;
}
}
Same visual result as mobile-first.

⚠️ Differences:

❌ Base CSS is desktop — mobile users download
desktop rules they'll never use, then download
overrides. Larger total payload.

❌ Mental model is "start big, undo." You have
to remember what the base rules were, then
what each max-width undoes.

❌ Cascade order matters — the last max-width
wins, so you must order breakpoints from
largest to smallest. Easy to get wrong.

✅ Mobile-first avoids all three problems.
Use min-width for new code.

✅ The standard breakpoints

Conventions, not rules. Pick where your design breaks.

breakpoints.css
/* Base — mobile /
/ Everything above 0px */

@media (min-width: 640px) { /* sm / }
@media (min-width: 768px) { / md / }
@media (min-width: 1024px) { / lg / }
@media (min-width: 1280px) { / xl / }
@media (min-width: 1536px) { / 2xl / }
These are Tailwind's defaults. They work for
most sites. But they're not rules — they're
conventions.

640px → small tablet / large phone landscape
768px → tablet portrait
1024px → tablet landscape / small desktop
1280px → desktop
1536px → large desktop

Better approach: pick breakpoints where
YOUR design breaks.

If your card grid looks cramped at 900px,
that's your breakpoint. Not 768px because
an iPhone happens to be 390px wide.

Design-driven > device-driven.

Modern alternative: use container queries
(@container) for components, and media
queries only for page-level layout.

Don't use device-specific breakpoints. @media (max-width: 375px) for "iPhone" is a common mistake. Devices change every year — the iPhone 15 is 393px wide, the iPhone 16 Pro Max is 440px. There is no stable "iPhone width." Use design-driven breakpoints: the point at which your layout starts to break, regardless of what device happens to be that wide. The result is CSS that works on every device, present and future, without updates.

⚠️ Common mistakes

The media-query mistakes that cost real time.

1. Mixing min-width and max-width

Confusing override order. Fix: pick one direction per project. Mobile-first (min-width) preferred.

2. Device-specific breakpoints

"iPhone" and "iPad" widths change. Fix: break at design points, not device widths.

3. Forgetting the viewport meta tag

Media queries don't fire without it. Fix: add .

4. Too many breakpoints

One rule per breakpoint, 8 breakpoints — unmaintainable. Fix: 3–5 breakpoints usually enough.

5. Using max-width with mobile-first base

Double override. Fix: min-width with mobile-first.

6. No only screen for print

@media print overrides screen rules if not careful. Fix: @media only screen and (...) when needed.

7. Testing only in DevTools

Real devices have different behavior (iOS Safari, Android Chrome). Fix: test on actual phones.

8. Ignoring reduced-motion

@media (prefers-reduced-motion: reduce) disables animations for users who need it. Fix: add it.

❓ Frequently asked

How do CSS media queries work?

A media query applies CSS only when a condition is true. Syntax: @media (min-width: 768px) { ... } — the rules inside only apply when the viewport is 768px or wider. Media queries are the foundation of responsive design: write base styles for the smallest screen, then add rules for larger screens with min-width. You can combine conditions with and: @media (min-width: 768px) and (max-width: 1023px).

What is the difference between min-width and max-width in media queries?

min-width: 768px matches viewports 768px and wider — used in mobile-first CSS. max-width: 767px matches viewports 767px and narrower — used in desktop-first CSS. Modern best practice is mobile-first with min-width. It's easier to reason about and results in smaller CSS.

What are the standard breakpoints?

There are no official breakpoints in CSS — you pick based on your content. Common conventions: 640px, 768px, 1024px, 1280px, 1536px. These match Tailwind CSS defaults. The important rule: pick breakpoints where your design breaks, not where devices happen to be.

What is mobile-first CSS?

Write your base CSS for the smallest screen, then add media queries with min-width for larger screens. The base styles apply everywhere; each media query adds complexity as the viewport grows. This is the modern default because most traffic is mobile, mobile is the hardest constraint, CSS grows logically, and the payload is smaller.

Can I use media queries for print styles?

Yes — @media print { ... } applies only when the page is printed. Use it to hide navigation, expand links to show their URL, remove background colors, and use serif fonts. Print stylesheets are a real accessibility feature. Most sites don't bother, but adding a minimal print stylesheet is a quick win.

What are container queries?

Container queries are a newer CSS feature that applies rules based on the size of a parent container, not the viewport. Syntax: @container (min-width: 400px) { ... }. This lets a card respond to its own width, not the screen's. Container queries are supported in all modern browsers since 2023.

🔗 Related

← All CSS problems
Problem solved · CSS