Responsive design
One page for every screen: fluid widths first, then a media query where the layout genuinely has to change.
Screens are not one size
A layout that works at 1440 pixels is not a layout that works at 360. Responsive design is the discipline of making one page answer both — and the surprise is how little of it needs special code.
Most of it is fluid: widths in % or max-width, type and spacing in rem, images with max-width: 100%. Those three habits mean the page bends instead of breaking, and a media query is only needed where the design has to change shape.
Images need one rule of their own: max-width: 100% and height: auto. Without it, an image keeps its intrinsic width and pushes the page wider than the screen; with it, the image shrinks with its container and keeps its proportions. Width and height attributes in the HTML are still useful — they tell the browser the aspect ratio before the file arrives, which stops the page jumping as it loads.
Fluid first, queries second
img { max-width: 100%; height: auto; }
@media (max-width: 40rem) {
.row {
flex-direction: column;
}
}The breakpoint should be where it breaks
There is no set of screen sizes to target; there is only the width at which your layout looks wrong. Drag the window narrower until the row is cramped, and that is your breakpoint — 40rem, 52rem, whatever the design says.
A media query adds or overrides rules at that width. Everything outside it keeps the base styles, so the base should be the version that works everywhere: stacked, simple, single-column.
Touch and the small print
Narrow screens are usually touched, so targets need to be at least 44 pixels across and nothing important should hide behind hover. If a menu only opens on hover, a phone never sees it.
And the page must carry <meta name="viewport" content="width=device-width, initial-scale=1"> in its head. Without it a phone pretends to be a desktop and zooms the page out, and no amount of CSS fixes it.
What a media query cannot fix
A query changes the rules that apply; it does not change the content inside them. A long unbroken URL, a wide table or a fixed-width image will overflow at every size until the element itself is allowed to shrink or scroll. max-width: 100%, overflow-wrap: anywhere and a wrapper with overflow-x: auto are the tools for that, and none of them needs a breakpoint.
The other thing a query cannot do is decide whether the layout is good. A page can pass every breakpoint and still be unpleasant at 320 pixels because the text is too large, the tap targets too close, or the heading wraps to four lines. Test the narrow width by reading and tapping, not only by checking that nothing overlaps.
Start from the narrow layout
A mobile-first stylesheet uses the unqueried rules for the narrow case and adds complexity with min-width queries as the window grows. That is not a slogan: the base is the version that cannot break, and every query only has to answer one question — what changes when there is more room?
Order matters because equal-specificity rules are applied in source order. A min-width: 40rem block written after the base wins at 40rem and above; below it, the base is all there is. Writing the desktop rules first and undoing them with max-width works too, but every override has to remember everything the desktop rule added.
What the query is measuring
A media query tests the viewport in CSS pixels, not the physical screen. min-width: 40rem means 40 times the browser’s default font size, so a reader who has enlarged that default gets the wider layout sooner — which is usually the intent, because their text needs more room.
Width is only one feature. prefers-color-scheme asks about the system theme, prefers-reduced-motion about animation, and hover about whether the pointer can hover at all. Each is a question about the reader’s device or settings, and each uses the same block syntax.
Three responsive mistakes: testing only the device presets in developer tools, which never show the layout at 320 pixels or with enlarged text; setting a fixed height on a hero so the copy clips when it wraps on a phone; and writing a max-width query for the phone after a desktop base, then wondering why a device just under the breakpoint gets the phone rules on top of the desktop ones.
Try these next
- Turn one
max-widthquery into a mobile-firstmin-widthquery and move the base rules underneath it. - At 320 pixels, find one element that overflows and fix it with
max-width: 100%ormin-width: 0. - Add a
prefers-reduced-motionblock and switch the setting on to see it apply.
A row that stacks when it must
The two columns sit side by side at every width, which is cramped on a phone. Add a media query so that below 40rem the row becomes a column.
3 left to do
- There is a media query
- It applies below a max-width
- The row stacks in the column direction
@media (max-width: 40rem) { .row { flex-direction: column; } } — the base styles stay as they are.
A footer that folds
The three footer sections are stacked at every width. Start from that stacked layout, then add one query: at 48rem and wider they should sit in three equal columns with a gap. Keep the narrow layout as the base.
3 left to do
- There is a media query
- The query starts at a min-width
- The wide footer has three columns
display: grid; gap: 1rem; on the footer, then @media (min-width: 48rem) { .footer { grid-template-columns: repeat(3, 1fr); } }.
Test by narrowing the window, not by simulating a phone. The real question is where the layout stops working, and the window answers it directly.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
How do you choose a breakpoint?
