CSS Media Queries: Complete Guide to Responsive Design
Master CSS media queries for building truly responsive layouts across all screen sizes.
What Are CSS Media Queries?
CSS media queries let you apply styles conditionally based on the characteristics of the user's device or viewport. Think of them as if statements in CSS: "if the screen is wider than 768px, apply these styles."
The core syntax looks like this:
@media <media-type> and (<media-feature>) {
/* styles applied when condition is true */
}
Media queries sit at the foundation of responsive CSS. While Flexbox and Grid handle internal layout fluidity, media queries control the structural shifts — when a sidebar collapses, when a nav becomes a hamburger menu, when a single column becomes three.
Core Syntax and Components
Media Types
The three media types you'll actually use:
screen— for screens (monitors, phones, tablets)print— for printed pagesall— matches everything (this is the default when omitted)
Most of your queries will target screen, or omit the type entirely since all is implied.
Media Features
Media features are the conditions inside parentheses. The most common is width, but there are many others:
/* Viewport width range */
@media (min-width: 768px) { }
/* Exact width (avoid this in practice) */
@media (width: 768px) { }
/* Device orientation */
@media (orientation: landscape) { }
/* Touch vs. pointer devices */
@media (hover: none) { } /* touch devices */
@media (hover: hover) { } /* mouse/trackpad */
@media (pointer: coarse) { } /* fat fingers */
/* User preferences */
@media (prefers-reduced-motion: reduce) { }
@media (prefers-color-scheme: dark) { }
Combining Conditions
Use and to require multiple conditions, or commas for OR logic:
/* Both conditions must be true */
@media screen and (min-width: 768px) and (orientation: landscape) {
.sidebar { display: block; }
}
/* Either condition triggers the styles */
@media (max-width: 600px), (orientation: portrait) {
.nav { flex-direction: column; }
}
Mobile-First vs. Desktop-First
This is the most consequential decision you'll make when writing responsive CSS. Mobile-first means you write base styles for small screens, then use min-width queries to progressively enhance for larger screens.
/* Mobile-first approach */
.nav {
display: flex;
flex-direction: column; /* stacked on mobile */
gap: 0.5rem;
}
@media (min-width: 768px) {
.nav {
flex-direction: row; /* horizontal on tablet+ */
gap: 2rem;
}
}
@media (min-width: 1024px) {
.nav {
justify-content: space-between;
}
}
Desktop-first does the opposite — base styles for large screens, max-width queries to scale down.
Mobile-first wins for most projects because:
- Mobile CSS loads first; desktop enhancements are additive
- You avoid the "undo" problem where mobile styles override desktop defaults
- It aligns with how browsers and search engines prioritize content
The exception: if you're building an internal tool or dashboard used primarily on desktop, desktop-first may feel more natural.
Choosing Your Breakpoints CSS
The biggest mistake developers make is targeting specific devices. Forget memorizing iPhone dimensions. Instead, let your content tell you where breakpoints belong.
Open your browser's dev tools, drag the viewport narrower, and watch where your layout breaks. That's where you add a breakpoint.
That said, here's a practical starting set of breakpoints that works well for most projects:
/* Base: mobile (no query needed) */
/* Small tablets and large phones */
@media (min-width: 480px) { }
/* Tablets */
@media (min-width: 768px) { }
/* Laptops and small desktops */
@media (min-width: 1024px) { }
/* Large desktops */
@media (min-width: 1280px) { }
Use em Units for Breakpoints
Pixel-based breakpoints ignore user browser font size settings. When a user sets their browser default to 20px, a 768px breakpoint behaves differently than expected. Use em instead:
/* 768px ÷ 16 = 48em */
@media (min-width: 48em) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
/* 1024px ÷ 16 = 64em */
@media (min-width: 64em) {
.grid { grid-template-columns: repeat(3, 1fr); }
}
Building a Responsive Grid
Here's a complete, copy-paste-ready responsive grid using mobile-first media queries. You can prototype the grid structure with our CSS Grid Generator before adding the responsive logic.
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.grid {
display: grid;
grid-template-columns: 1fr; /* 1 column: mobile */
gap: 1rem;
padding: 1rem;
max-width: 1200px;
margin: 0 auto;
}
.card {
background: #f5f5f5;
border-radius: 8px;
padding: 1.5rem;
border: 1px solid #e0e0e0;
}
/* Tablet: 2 columns */
@media (min-width: 48em) {
.grid {
grid-template-columns: repeat(2, 1fr);
gap: 1.5rem;
padding: 1.5rem;
}
}
/* Desktop: 3 columns */
@media (min-width: 64em) {
.grid {
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
padding: 2rem;
}
}
/* Landscape phones: slight gap increase */
@media (orientation: landscape) and (max-width: 47.9em) {
.grid { gap: 1.5rem; }
}
</style>
</head>
<body>
<div class="grid">
<div class="card"><h2>Card One</h2><p>Content here.</p></div>
<div class="card"><h2>Card Two</h2><p>Content here.</p></div>
<div class="card"><h2>Card Three</h2><p>Content here.</p></div>
<div class="card"><h2>Card Four</h2><p>Content here.</p></div>
<div class="card"><h2>Card Five</h2><p>Content here.</p></div>
<div class="card"><h2>Card Six</h2><p>Content here.</p></div>
</div>
</body>
</html>
Don't forget the <meta name="viewport"> tag — without it, mobile browsers render at desktop width and your media queries effectively stop working.
Modern Feature Queries Worth Using
Respecting User Preferences
These queries tap into OS-level settings and meaningfully improve accessibility:
/* Respect reduced motion preferences */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
/* Dark mode support */
@media (prefers-color-scheme: dark) {
:root {
--bg: #1a1a1a;
--text: #f0f0f0;
--border: #333;
}
}
/* Light mode (default) */
:root {
--bg: #ffffff;
--text: #1a1a1a;
--border: #e0e0e0;
}
body {
background-color: var(--bg);
color: var(--text);
}
Adapting for Touch Devices
/* Default: assume hover-capable device */
.btn {
transition: background-color 0.2s ease;
}
.btn:hover {
background-color: #0056b3;
}
/* Touch devices: remove hover effects, increase tap targets */
@media (hover: none) and (pointer: coarse) {
.btn {
min-height: 44px; /* Apple's recommended tap target */
min-width: 44px;
}
.btn:hover {
background-color: inherit; /* disable hover on touch */
}
}
Container Queries: The Modern Complement
Container queries are now universally supported (Chrome/Edge 105+, Firefox 110+, Safari 16+) and solve a problem media queries can't: component-level responsiveness based on the component's own size, not the viewport.
/* Set up the container */
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* Style the card based on its container width */
.card {
display: flex;
flex-direction: column;
gap: 1rem;
}
/* When the card-wrapper is at least 400px wide */
@container card (min-width: 25rem) {
.card {
flex-direction: row;
align-items: center;
}
.card__image {
width: 200px;
flex-shrink: 0;
}
}
This approach means you can drop .card-wrapper into a narrow sidebar or a full-width section, and the card will respond to its actual available space — not the viewport width. This makes components genuinely reusable.
Use container queries for component-level adaptation and viewport media queries for page-level structural shifts. They complement each other.
Avoiding Common Mistakes
Avoid overlapping ranges. If you use both min-width and max-width queries, be careful about which ranges share a boundary:
/* Problem: 768px matches BOTH queries */
@media (max-width: 768px) { }
@media (min-width: 768px) { }
/* Fix: use 769px or shift to mobile-first min-width only */
@media (max-width: 767px) { }
@media (min-width: 768px) { }
Don't overuse media queries. If you find yourself writing dozens of queries, you probably need more fluid base styles. The Flexbox Generator can help you build flex layouts that adapt without breakpoints. Intrinsic sizing with clamp(), minmax(), and auto-fit often eliminates entire breakpoints.
Keep queries close to components. Scattering all your media queries at the bottom of a massive stylesheet makes maintenance painful. Co-locate them with the component they affect:
/* ✅ Component-organized */
.nav { /* base styles */ }
@media (min-width: 48em) { .nav { /* tablet */ } }
@media (min-width: 64em) { .nav { /* desktop */ } }
.hero { /* base styles */ }
@media (min-width: 48em) { .hero { /* tablet */ } }
Browser Compatibility
Basic media queries (min-width, max-width, orientation) work in every browser including IE9+, so you have effectively 100% coverage there. Modern features:
| Feature | Chrome | Firefox | Safari |
|---|---|---|---|
min-width / max-width |
All | All | All |
prefers-color-scheme |
76+ | 67+ | 12.1+ |
prefers-reduced-motion |
74+ | 63+ | 10.1+ |
| Container queries | 105+ | 110+ | 16+ |
hover / pointer |
38+ | 64+ | 9+ |
For container queries, you can progressively enhance with @supports:
@supports (container-type: inline-size) {
.card-wrapper {
container-type: inline-size;
}
}
Format your CSS cleanly before production — the CSS Formatter can help normalize inconsistent whitespace in media query blocks.
Next Steps
Now that you understand the fundamentals of CSS media queries, here's where to go next:
- CSS Grid Generator — Visually build grid layouts that you can then make responsive with the techniques in this guide
- Flexbox Generator — Generate flexible container styles that reduce how many breakpoints you need
- CSS Formatter — Clean up and normalize your responsive CSS before shipping
From here, dig deeper into:
- CSS
clamp()and fluid typography — Replace some breakpoints with smooth scaling usingclamp(1rem, 2.5vw, 1.5rem) - CSS Grid's intrinsic sizing —
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr))creates responsive grids with zero media queries - Container query units —
cqi,cqb, and related units let you size elements proportionally to their container
The best responsive CSS uses media queries strategically, not exhaustively. Combine them with fluid layouts and modern sizing functions, and you'll write far less code while supporting far more devices.
Related Tools
CSS Grid Generator
Visual CSS Grid layout builder. Define columns, rows, gaps, and areas with live preview.
Flexbox Generator
Visual Flexbox layout builder with all flex properties. See changes in real-time.
CSS Formatter
Beautify and format CSS code with proper indentation and structure.
CSS Unit Converter
Convert between CSS units: PX, REM, EM, PT, VW, and degrees/radians.
Continue Learning
Responsive Web Design: Building for All Devices
Learn responsive design techniques including media queries, flexible layouts, and mobile-first approach.
intermediateCSS Flexbox: Complete Layout Guide
Master Flexbox for creating flexible, responsive layouts with ease.
intermediateCSS Grid: The Ultimate Layout System
Learn CSS Grid for creating complex, two-dimensional layouts with precision.