Media Queries, Breakpoints and Container Queries
IntermediateWrite mobile-first, choose breakpoints from where your content breaks rather than from device names, and use container queries when a component should respond to its own space.
Overview
Responsive design in India is not a nicety — the large majority of traffic is a phone, often a mid-range Android on a variable connection. Mobile-first means the base stylesheet is the phone layout and min-width queries add complexity for larger screens, which keeps the smallest devices doing the least work. Breakpoints should come from the content: widen the browser until the layout looks wrong, and put one there. Container queries then close the remaining gap, because a card in a sidebar needs a different layout from the same card in a full-width grid, and the viewport cannot tell you which it is in.
Mobile-First
Base styles are the phone; min-width queries add from there.
/* Base: the smallest screen, no query needed */
.grid { display: grid; gap: 1rem; grid-template-columns: 1fr }
/* Then add complexity upwards */
@media (min-width: 48rem) { /* 768px */
.grid { grid-template-columns: repeat(2, 1fr) }
}
@media (min-width: 64rem) { /* 1024px */
.grid { grid-template-columns: repeat(3, 1fr) }
}
/* Desktop-first (max-width) means a phone parses every desktop rule
and then overrides it — more CSS to override, and the smallest
device does the most work. */
/* Use rem in the query, not px: the query then respects the user's
font size, so a zoomed-in user gets the simpler layout that fits.
/* Modern range syntax, where supported */
@media (width >= 48rem) { }
@media (48rem <= width <= 64rem) { }
/* Breakpoints from content, not from device names. There is no
"iPhone width" worth targeting — there are dozens. Common
starting values, to be adjusted once you see your content:
40rem (640) 48rem (768) 64rem (1024) 80rem (1280) */Container Queries
A component responding to its own width, which is what you actually wanted.
/* The problem: the same card in two places needs two layouts, and
a media query only knows the viewport. */
.card-area { container-type: inline-size; container-name: card }
@container card (min-width: 24rem) {
.card { display: grid; grid-template-columns: 8rem 1fr; gap: 1rem }
}
/* Now the card goes horizontal whenever ITS container is wide
enough — in a wide grid on a phone, or narrow in a desktop
sidebar. One component, correct everywhere. */
/* Container query units, relative to the container rather than the
viewport */
font-size: clamp(1rem, 5cqi, 1.5rem) /* cqi = inline size */
/* Style queries — respond to a custom property on an ancestor */
@container style(--variant: compact) { .card { padding: .5rem } }
/* Caveat: container-type: inline-size makes the element a
containment context, which means it can no longer be sized by its
own children in that axis. Apply it to a WRAPPER, not to the
component you are styling. */Querying the User, Not the Screen
Preference and capability queries, which matter as much as width.
/* Motion — vestibular disorders make large animations painful */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .01ms !important;
transition-duration: .01ms !important;
scroll-behavior: auto !important;
}
}
/* Colour scheme */
@media (prefers-color-scheme: dark) { }
@media (prefers-contrast: more) { }
/* Input capability — a phone has no hover, and a sticky hover state
that will not clear is a common mobile bug */
@media (hover: hover) and (pointer: fine) {
.card:hover { transform: translateY(-2px) }
}
@media (pointer: coarse) {
.button { min-height: 44px } /* a fingertip target */
}
/* Orientation and print */
@media (orientation: landscape) { }
@media print { nav, .no-print { display: none } }
/* Data saving */
@media (prefers-reduced-data: reduce) { .hero { background-image: none } }Key Points to Remember
- 1Mobile-first with min-width means the smallest device parses the least CSS and overrides nothing
- 2Breakpoints in rem respect the user's font size; breakpoints chosen from content beat device-named ones
- 3Container queries let a component respond to its own width, which a media query cannot express
- 4container-type creates a containment context, so apply it to a wrapper rather than the styled component
- 5prefers-reduced-motion, hover and pointer queries matter as much as width — a phone has no hover and needs 44px targets
Interview Questions
Sign in to ask AriaWhy is mobile-first CSS preferred over desktop-first?
What can a container query do that a media query cannot?
Why should hover effects be wrapped in @media (hover: hover)?
Ask Aria about Media Queries, Breakpoints and Container Queries
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.