Responsive layout
Why you need this
More than half of people open sites on a phone. A phone screen is 360–430 pixels wide, a tablet about 800, a laptop 1300 and more. Responsive layout means one and the same page looks good on any of them: three columns on a computer, one on a phone, the menu turns into a button. Google even ranks non-responsive sites lower in search.
The viewport meta tag
Without it a phone pretends its screen is 980px wide and shows the site tiny, like on a computer.
So every page has this in its <head>:
<meta name="viewport" content="width=device-width, initial-scale=1">
It means: "the page width = the device screen width, scale 1:1". Without this line media queries won't work properly on a phone.
Relative units
Pixels (px) are a rigid unit: 300px is always 300px, even on a 320px-wide screen.
So responsive layout often uses relative units:
| Unit | Relative to |
|---|---|
% |
the size of the parent |
em |
the font size of this element |
rem |
the font size of the root (html), usually 16px |
vw |
1% of the window width (viewport width) |
vh |
1% of the window height |
html { font-size: 16px; }
h1 { font-size: 2rem; } /* 32px */
.btn { padding: 0.5em 1em; } /* the padding grows with the button's font */
.hero { height: 100vh; } /* a banner the full height of the screen */
.col { width: 50%; } /* half of the parent */
Result: a 32px heading; a button with a big font gets bigger padding by itself; the banner is exactly the window's height.
rem is handy for fonts: if the user enlarges the font in the browser settings, the whole page scales neatly.
Flexible images
An 800px picture in a 300px column sticks out over the edge. Two lines fix it:
img {
max-width: 100%;
height: auto;
}
Result: the picture is never wider than its parent; on a narrow screen it shrinks, keeping its proportions.
Media queries
A media query is CSS rules that work only under a condition:
.menu { display: none; }
@media (min-width: 600px) {
.menu { display: flex; }
}
Result: on screens narrower than 600px the menu is hidden; from 600px and wider it is shown.
min-width: 600px— "window width from 600px";max-width: 599px— "window width up to 599px".
Inside @media { … } there are ordinary CSS rules. They override the same rules above them in the
cascade (media queries are written after the main rules).
Mobile first
There are two approaches:
- mobile first: the main rules are for a narrow screen, and
min-widthmedia queries add columns on wide ones; - desktop first: the other way round, the base is for a computer, and
max-widthsimplifies things for a phone.
Today mobile first is the norm: on a phone the site is simple and fast, and complexity is added where there's room.
.grid { display: grid; grid-template-columns: 1fr; gap: 16px; }
@media (min-width: 600px) {
.grid { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1000px) {
.grid { grid-template-columns: 1fr 1fr 1fr 1fr; }
}
Result: one column on a phone, two on a tablet, four on a big screen.
Typical breakpoints: 600px (big phone/tablet), 900px (tablet/laptop), 1200px (big screen). But it's better to put them where your layout starts to feel cramped.
How to check it
In the browser press F12 and the phone icon («Toggle device toolbar») — you can pick an iPhone or set any width and watch how the page rearranges. Or just make the window narrower with the mouse.
How it works inside
Every time the window is resized, the browser re-checks the conditions of all media queries. The rules of matching queries take part in the cascade, non-matching ones are as if they didn't exist. That's why the layout rearranges instantly when you turn a phone.
Common mistakes
- No viewport meta tag. On a phone the site is tiny and media queries "don't work".
- A media query above the main rule. The main rule below overrides it. Put
@mediaat the end. min-widthin reverse order. If 900px comes before 600px, the 600px rule wins on a wide screen.- A fixed width in px.
width: 1000px— a phone gets a horizontal scrollbar. Usemax-width: 1000pxand percentages. - A space in the condition.
@media (min-width:600 px)— there must be no space between the number andpx.
Cheat sheet
| Code | What it does |
|---|---|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
normal scale on a phone |
%, em, rem, vw, vh |
relative units |
img { max-width: 100%; height: auto; } |
flexible images |
@media (min-width: 600px) { … } |
rules from 600px and wider |
@media (max-width: 599px) { … } |
rules up to 599px |
| mobile first | the base is for a phone, min-width in ascending order |