Skip to main content

Why media queries are needed in CSS

Media queries are CSS rules that apply styles conditionally based on device characteristics like screen width, orientation, or color scheme.

Theory

TL;DR

  • Media queries work like a waiter who adjusts the plate size depending on the table: same food, different presentation for different needs.
  • Without them, one CSS file forces the same layout on all screens. A three-column grid that looks clean at 1440px becomes unreadable on a 375px phone.
  • Use max-width for desktop-first, min-width for mobile-first (the preferred approach).
  • They activate instantly on resize, no JavaScript needed.

Quick example

css
/* Base: 3-column grid on desktop */ .card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; } /* Phone: screen under 600px → single column */ @media (max-width: 600px) { .card-grid { grid-template-columns: 1fr; /* cards stack vertically, no horizontal scroll */ } }

Desktop shows 3 cards side by side. On a 375px phone they stack into one column automatically.

Why fixed styles fail

A stylesheet without media queries locks every device into the same layout. The browser picks one rule set and applies it everywhere, screen size irrelevant. Media queries let the browser evaluate the actual viewport at render time and activate only the matching rule blocks. Same stylesheet, different behavior per device.

When to use

  • Mobile-first: base mobile styles first, then @media (min-width: 768px) for wider screens.
  • Print: @media print { .no-print { display: none; } } strips navigation from printed pages.
  • Dark mode: @media (prefers-color-scheme: dark) { body { background: #000; } }.
  • Orientation: @media (orientation: landscape) { video { height: 100vh; } }.
  • Accessibility: @media (prefers-reduced-motion: reduce) { * { animation: none; } }.

How the browser handles it

Browsers parse all CSS upfront. At render time, the layout engine (Blink in Chrome, Gecko in Firefox) evaluates each media feature against the current viewport through window.matchMedia(). When the viewport changes, matching rule sets activate instantly. No page reload, no recalculation for elements outside the matched rules.

Common mistakes

Using width instead of min-width or max-width:

css
/* Wrong: matches exactly 768px and nothing else */ @media (width: 768px) { ... } /* Right: matches 768px and below */ @media (max-width: 768px) { ... }

Desktop-first base with mobile as an afterthought:

css
/* Wrong: mobile accidentally inherits 3-column base if the override is missing */ .grid { grid-template-columns: repeat(3, 1fr); } @media (max-width: 768px) { .grid { grid-template-columns: 1fr; } } /* Right: mobile-first, add complexity for wider screens */ .grid { grid-template-columns: 1fr; } @media (min-width: 769px) { .grid { grid-template-columns: repeat(3, 1fr); } }

Nesting media queries (one of the most common CSS bugs on Stack Overflow):

css
/* Wrong: browsers ignore the inner query entirely */ @media (max-width: 768px) { .parent { @media (max-width: 480px) { .child {} } } } /* Right: flatten both queries */ @media (max-width: 480px) { .child {} }

I've watched devs spend an hour on a layout that looked fine on desktop but broke on mobile, only to find they had nested two queries and the inner one was just ignored the whole time.

Real-world usage

  • Tailwind CSS: breakpoints like md: generate @media (min-width: 768px) automatically.
  • Bootstrap 5: uses @media (min-width: 576px) for .container width adjustments.
  • React apps: @media (max-width: 1024px) { .menu-toggle { display: block; } } for hamburger nav.
  • Next.js 14: global CSS with media queries for page-level responsive layout.

Follow-up questions

Q: What is the difference between @media (max-width: 768px) and viewport units like vw?
A: max-width switches entire rule sets at a specific breakpoint. vw scales a single property continuously, like font-size: 5vw. Media queries give discrete layout changes; viewport units give gradual scaling.

Q: How does dark mode work with CSS?
A: @media (prefers-color-scheme: dark) { body { background: #000; color: #fff; } }. The browser reads the OS setting and applies the styles automatically, no JavaScript needed.

Q: What are container queries and how do they differ from media queries?
A: Media queries respond to the viewport size. Container queries (@container) respond to the size of a parent element, which makes components reusable regardless of placement. Supported in Chrome 105+ and Firefox 110+.

Q: How do you debug a media query not applying on iOS Safari?
A: Check for the viewport meta tag first: <meta name="viewport" content="width=device-width, initial-scale=1">. Without it, iOS renders at desktop scale and pixel-based breakpoints behave unpredictably. Also verify any -webkit- prefixed features you are using.

Examples

Basic: padding adjustment by screen size

css
.hero { padding: 100px 40px; /* desktop: generous spacing */ } @media (max-width: 768px) { .hero { padding: 20px 10px; /* mobile: compact */ } }

On a 1920px monitor you get 100px top/bottom padding. On a 375px iPhone it drops to 20px. Same element, two behaviors, zero JavaScript.

css
.nav-bar { display: flex; justify-content: space-between; /* horizontal on desktop */ } .menu-toggle { display: none; /* hamburger hidden on desktop */ } @media (max-width: 1024px) { .nav-bar { flex-direction: column; /* stacks vertically for smaller screens */ } .menu-toggle { display: block; /* hamburger icon appears */ } }

This pattern shows up in every production app with a responsive nav, from GitHub to Vercel's dashboard. The toggle button only appears when the screen is too narrow for a horizontal bar. CSS handles the entire layout change.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?