Media Queries and Breakpoints
Introduction
Fluid layout patterns solve many responsive problems, but not all of them. At some viewport ranges, typography, navigation, spacing, or component structure still needs explicit adaptation. This chapter explains media query syntax, breakpoint strategy, and a maintainable mobile-first workflow for real-world CSS.
Prerequisites
- Responsive design basics
- Familiarity with CSS units and fluid sizing
- Basic Grid and Flexbox usage
What Media Queries Do
Media queries let you apply CSS conditionally based on environment characteristics, most commonly viewport width.
Basic syntax:
@media (min-width: 768px) {
.container {
max-width: 720px;
}
}Meaning:
- apply enclosed styles only when condition is true
min-width: 768pxmeans this block activates at768pxand abovemax-width: 720pxkeeps long lines readable on larger screens
Most responsive work uses width conditions, but media queries can also target print, orientation, and user preferences.
Mobile-First with min-width
Recommended approach:
- write base styles for small screens
- progressively enhance with
min-widthbreakpoints
Example:
.nav {
display: grid;
gap: 0.5rem;
}
@media (min-width: 768px) {
.nav {
display: flex;
align-items: center;
gap: 1rem;
}
}Why this works well:
- smaller defaults stay simple
- larger screens get additive enhancements
- fewer override conflicts
Code explanation:
- base
.navusesgridfor compact mobile stacking - at
768px+, layout switches toflexfor horizontal alignment align-items: centervertically aligns nav contentgapincreases from0.5remto1remfor desktop breathing room
max-width Queries
max-width is also valid:
@media (max-width: 767px) {
.sidebar {
display: none;
}
}Use carefully:
- excessive
max-widthpatches can become hard to maintain
Code explanation:
- condition applies only at
767pxand below display: noneremoves sidebar from layout entirely on small screens- this is useful for dense secondary panels, but ensure navigation still remains accessible
In most teams, mobile-first + min-width is easier long-term.
Common Breakpoint Ranges (Guideline)
Project-specific breakpoints vary, but a common pattern is:
- base: mobile-first default
@media (min-width: 600px)for larger phones/small tablets@media (min-width: 900px)for tablet/desktop transition@media (min-width: 1200px)for wide desktop refinements
These are starting points, not strict standards.
Tip
Break on Content, Not Device Names
Add a breakpoint where layout quality drops, not because a specific phone model exists.
Organizing Breakpoints in CSS
Two common patterns:
- Component-local queries: keep media rules near component styles
- Centralized breakpoint sections: group all responsive rules by width
For most modern codebases, component-local organization is easier to read and maintain.
Example:
Code explanation:
- mobile default is a single-column list (
1fr) - at
700px+, it becomes 2 columns withrepeat(2, 1fr) - at
1024px+, it expands to 3 columns - this is a classic progressive enhancement breakpoint pattern
Combining Conditions
You can combine conditions with and:
@media (min-width: 768px) and (max-width: 1023px) {
.banner {
padding: 1.5rem;
}
}Useful for targeted tuning in a middle range.
Code explanation:
- both conditions must be true (
and) - this targets the medium range only (roughly tablet width)
- only
.bannerpadding is tuned, keeping the override narrowly scoped
Avoid over-fragmenting into many tiny ranges unless truly needed.
Orientation Queries
Orientation can be useful for specific UI elements:
@media (orientation: landscape) {
.hero {
min-height: 70vh;
}
}Do not rely only on orientation for major layout logic; width-based behavior is usually more stable.
Code explanation:
- rule applies when viewport is wider than tall (landscape)
min-height: 70vhensures hero keeps visual presence in horizontal modevhmeans percentage of viewport height
Print Media Query
For print-friendly output:
@media print {
nav,
.actions,
.ads {
display: none;
}
body {
color: #000;
background: #fff;
}
}Useful for docs, invoices, and report pages.
Code explanation:
@media printruns only for print preview/printing- navigation/actions/ads are hidden to reduce noise
- body colors switch to black-on-white for print readability
Preference-Based Queries
Modern media queries can respect user settings:
Reduced motion
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}Code explanation:
- activates when user OS/browser requests reduced motion
- disables transitions and animations to reduce vestibular discomfort
!importantensures these accessibility overrides win over component animation rules
Dark mode preference
@media (prefers-color-scheme: dark) {
:root {
--bg: #0b1220;
--text: #e2e8f0;
}
}These improve accessibility and user comfort.
Code explanation:
- activates when user prefers dark mode at system level
- updates root CSS variables (
--bg,--text) - components using these tokens automatically switch theme without rewriting each selector
Breakpoint Token Strategy
Defining shared breakpoint tokens improves consistency across files:
/* Example convention (comments or preprocessor vars) */
/* sm: 600px, md: 900px, lg: 1200px */Code explanation:
- this block documents shared breakpoint semantics for teams
- even without native media-query variables in plain CSS, a clear convention reduces inconsistent breakpoint usage
In plain CSS, custom properties cannot directly parameterize media query conditions in all contexts, so teams often document constants in conventions, design docs, or preprocessor config.
Common Mistakes
| Mistake | Why it hurts | Better approach |
|---|---|---|
| Too many breakpoints | Hard-to-maintain CSS | Start minimal, add only where needed |
| Device-specific targeting | Quickly outdated rules | Use content-driven width thresholds |
| Desktop-first overrides only | Complex cascade conflicts | Use mobile-first base + min-width enhancements |
| Large structural change at tiny range | Jumpy UX | Keep layout transitions gradual |
| Ignoring real-device testing | Hidden usability issues | Test on at least one physical phone/tablet |
Debugging Media Queries
When responsive styles do not apply:
- check current viewport width in DevTools
- confirm media condition actually matches
- inspect if rule is overridden by later/specific selector
- verify CSS file load order
- test by temporarily forcing the rule outside query
DevTools usually shows inactive media query blocks clearly.
Mini Exercise
- Create a simple page with header, nav, and card list
- Write mobile-first base styles
- Add one breakpoint at
700pxfor 2-column cards - Add one breakpoint at
1024pxfor 3-column cards - Add a
prefers-reduced-motionblock for animations - Verify behavior in responsive mode and on a real mobile device
FAQ
Should I always use min-width media queries?
For mobile-first workflows, usually yes. max-width is still useful in specific patch scenarios.
How many breakpoints should a typical page have?
Often two to four well-chosen breakpoints are enough, especially with fluid layout patterns.
Can Grid/Flex replace media queries completely?
No. They reduce breakpoint needs, but media queries are still essential for structural and typographic adjustments.
Why is my media query rule visible in CSS but not applied?
Either the condition does not match current viewport, or another rule wins by specificity/order.
Should I define breakpoints by popular device widths?
Prefer content-driven breakpoints. Device lists change constantly; content requirements are more stable.