Responsive design means one page that works on any screen. There is no separate mobile site — the same HTML rearranges itself.
Start with the viewport tag#
<meta name="viewport" content="width=device-width, initial-scale=1">Without this, a phone pretends to be about 980px wide and shrinks your whole page. Your media queries never trigger and text becomes unreadable. If a site looks tiny on mobile, this is the first thing to check.
Mobile first#
Write the styles for a narrow screen first, then add rules for wider ones using min-width:
/* base — applies everywhere, phone included */
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 16px;
}
@media (min-width: 640px) {
.grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 960px) {
.grid { grid-template-columns: repeat(3, 1fr); }
}This is easier than the reverse because a phone layout is naturally a single column. You add complexity as space appears, rather than stripping it away.
Breakpoints#
Do not chase specific device sizes — there are too many, and they change. Add a breakpoint where your layout starts to look wrong. Resize the browser slowly; the point where the design breaks is your breakpoint.
Three is usually plenty: around 640px, 960px and 1200px.
Layouts that adapt on their own#
Often you need no media query at all:
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 20px;
}
.row {
display: flex;
flex-wrap: wrap; /* items drop to a new line when space runs out */
gap: 16px;
}Flexible type and spacing#
h1 {
font-size: clamp(1.75rem, 5vw, 3rem);
}
.section {
padding: clamp(40px, 8vw, 96px) 20px;
}clamp(min, preferred, max) scales smoothly with the screen but never goes beyond the bounds you set. It replaces a lot of media queries.
Images and media#
img, video, iframe {
max-width: 100%;
height: auto;
display: block;
}Three lines that prevent the single most common cause of mobile overflow. Also set width and height attributes in the HTML so the browser reserves the right space and the page does not jump as images load.
The four causes of horizontal scrolling#
- A fixed width wider than the screen. Use
max-widthinstead ofwidth. - An image or video with no
max-width: 100%. - A wide table or code block. Wrap it:
<div style="overflow-x:auto">. - Long unbroken text such as a URL. Add
overflow-wrap: break-word.
To find the culprit, run this in the console:
document.querySelectorAll("*").forEach(el => {
if (el.getBoundingClientRect().right > document.documentElement.clientWidth) {
console.log(el);
}
});Touch targets#
Anything tappable should be at least 44 by 44 pixels with space around it. Links crammed together in a list are frustrating on a phone even when they look fine on a laptop.
.nav a {
display: inline-block;
padding: 12px 16px;
}Respecting user preferences#
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; transition: none !important; }
}
@media (prefers-color-scheme: dark) {
:root { --bg: #0c0e14; --ink: #f2f4f9; }
}Two short blocks that make a site noticeably more considerate.
Questions people ask#
What widths should I test?
375px covers most phones, 768px tablets, and 1280px or 1440px laptops. Also test a very wide window — layouts often stretch badly past 1600px.
Should I use rem or px for breakpoints?
em or rem breakpoints respect a user’s browser font-size setting, so the layout adapts when someone increases text size. It is a small accessibility win.
Do I need a separate mobile site?
No. One responsive site is easier to maintain and better for search. Separate mobile sites are largely a thing of the past.