Media Queries & Responsive Design
Responsive design makes one page work on every screen. Fluid layouts, flexible images and intrinsic techniques do most of the work; media queries step in where a layout needs to change shape at certain widths — or adapt to user preferences like dark mode and reduced motion.
Media query syntax
Rules inside @media (condition) apply only when the condition is true. The modern range syntax (width >= 600px) is clearer than the older min-width: 600px, which means the same thing; both work in all current browsers.
Mobile-first
Write the base styles for small screens first, then use min-width-style queries to add complexity as space grows. Small screens get the simplest CSS, and the code reads in order of increasing size.
Choosing breakpoints
Don't target specific devices — there are thousands. Instead, resize your browser until the design starts to look awkward, and put a breakpoint there. Many projects settle on a few, roughly:
| Width | Typical layout |
|---|---|
| Under ~600px | Single column (phones) |
| ~600–1000px | Two columns, sidebar may drop below (tablets, small laptops) |
| Over ~1000px | Full layout with a maximum content width |
Using em units in media queries (width >= 40em) makes breakpoints respond to the user's text size as well.
Combining conditions
@media (width >= 600px) and (width < 1000px) {
.sidebar { display: none; }
}
@media (orientation: landscape) and (height < 500px) {
.site-header { position: static; }
}
@media (hover: hover) and (pointer: fine) {
.card:hover { transform: translateY(-4px); }
}
@media print {
nav, .ads { display: none; }
a::after { content: " (" attr(href) ")"; }
}
| Feature | Detects |
|---|---|
width, height | Viewport size |
orientation | Portrait or landscape |
hover, pointer | Mouse vs touch |
prefers-color-scheme | Light or dark mode |
prefers-reduced-motion | The user wants less animation |
prefers-contrast, forced-colors | High-contrast settings |
print, screen | Media type |
User preferences
Fluid first, breakpoints second
Many layouts need fewer media queries than you'd expect. Prefer techniques that adapt continuously:
- Grid with
repeat(auto-fit, minmax(…, 1fr))(lesson 29). - Flexbox with
flex-wrapand aflex-basis(lesson 28). clamp()for type and spacing (lesson 14).max-widthon images and containers.- Container queries for components (next lesson).
The viewport meta tag
None of this works on phones without the viewport meta tag in your HTML head:
<title>Responsive</title> <meta name="viewport" content="width=device-width, initial-scale=1">
Testing
Use your browser's responsive design mode (Ctrl+Shift+M in Chrome and Firefox) to try many sizes, and check on real phones for touch behaviour and performance.