How do you make a web app responsive (media queries, relative units)
Fluid layouts (flex/grid + %), relative units (`rem`/`em`/`ch`/`vw`/`vh`), breakpoints via `@media (min-width)` (mobile-first), `clamp()` for fluid type, container queries for component-local responsiveness, `<picture>`/srcset for images, and a viewport meta tag. Layer with logical properties (`margin-inline`) for i18n/RTL.
Responsiveness today is fluid by default, breakpoints for layout shifts, components query their own container — not just one fixed grid that snaps at 768px.
1. Viewport tag
<meta name="viewport" content="width=device-width, initial-scale=1">Without it, mobile defaults to a ~980px layout. See [[why-does-the-viewport-meta-tag-matter-for-mobile-ui]].
2. Relative units
| Unit | When |
|---|---|
rem | Type, spacing scale (honors user font-size preference). |
em | Component-local sizing relative to parent. |
% | Layout widths. |
vw/vh / svh/dvh | Viewport-relative sizing; prefer dvh over vh on mobile. |
ch | Optimal text measure (max-width: 65ch). |
clamp(min, ideal, max) | Fluid type / spacing. |
clamp(1rem, 0.8rem + 1vw, 1.5rem) — type fluidly scales between bounds.
3. Mobile-first media queries
.card { padding: 1rem; }
@media (min-width: 48em) { .card { padding: 2rem; } }
@media (min-width: 80em) { .card { padding: 3rem; } }Use em units in queries so user zoom shifts breakpoints consistently.
4. Container queries
.card-wrap { container-type: inline-size; }
@container (min-width: 30em) { .card { display: flex; } }The component reacts to its own width, not the viewport — essential for design systems.
5. Layouts: flex + grid
- Flex for one-axis (rows of items).
- Grid for two-axis layouts (
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr))auto-wraps).
6. Responsive images
<img srcset="x-400.jpg 400w, x-800.jpg 800w" sizes="(min-width:48em) 50vw, 100vw" src="x-800.jpg">Or <picture> with <source media> for art direction.
7. Logical properties
margin-inline, padding-block, inset-inline-start — work for LTR + RTL without flipping styles.
8. Touch / pointer
@media (hover: hover) { ... } for hover-only effects on devices that actually hover.
9. Density
@media (prefers-color-scheme: dark), (prefers-reduced-motion), (prefers-contrast: more) — respect user OS settings.
Interview framing
"Fluid layouts with flex/grid, relative units (rem for type, % and fr for layout, clamp for fluid scale), mobile-first @media (min-width) in em units, and container queries for component-local responsiveness. Responsive images via srcset/sizes. Logical properties for i18n. Respect user prefs (prefers-color-scheme, prefers-reduced-motion). And the viewport meta tag is non-negotiable."
Follow-up questions
- •Why prefer container queries over media queries for components?
- •When would you use vw vs %?
- •How do you handle responsive images for art direction?
Common mistakes
- •px breakpoints that ignore user zoom.
- •Forgetting the viewport meta tag.
- •Hardcoding heights with vh on mobile (mobile chrome shifts vh).
Performance considerations
- •Avoid heavy layout-shifting media queries on resize. Use container queries to scope work. Responsive images cut bytes massively.
Edge cases
- •iOS safe areas with notch — env(safe-area-inset-*).
- •Soft keyboard collapses viewport (visualViewport API).
- •RTL — logical properties or directional CSS.
Real-world examples
- •Every modern marketing site, Tailwind's mobile-first defaults, GitHub UI.