Frontend Development · Tutorial 4 of 5
Responsive Design with Media Queries: a worked example
By the FUTEAC Team · 2 November 2026 · 10 min read · Beginner
In short
A media query is a CSS rule that asks the browser a question — "is this screen narrower than 768 pixels?" — and applies extra styles only when the answer is yes. Write your CSS once, then add a few @media blocks that rearrange the layout at chosen widths, called breakpoints. One page, one codebase, readable on phones and desktops.
- Responsive means one page that adapts. The same HTML and CSS rearranges itself as the screen shrinks — not a separate "mobile site" and not a shrunken desktop page.
- The viewport meta tag comes first. Without it, phones render your page at desktop width and zoom out, and your media queries look broken. One line in
<head>fixes it. - Breakpoints follow your layout, not phone models. You add a breakpoint where *your* design starts looking wrong — commonly around 1024, 768 and 480 pixels — not one per device on the market.
- Order matters in the cascade. With
max-widthqueries, write the widest breakpoint first and the narrowest last, so each narrower rule wins over the wider one. - This tutorial feeds the HTML & CSS Foundations course (/course/html-css-foundations) and the Responsive Design (/skill/responsive-design) skill.
Before you start
What does "responsive" actually mean?
Open any page on your phone that was designed only for a desktop: tiny text, horizontal scrolling, buttons you cannot tap without zooming. That page is not responsive. A responsive page is one where the same HTML and CSS rearranges itself to fit whatever screen it lands on — three columns become one, the navigation collapses, type stays readable — with no separate mobile version and no zooming required.
Two ideas it is often confused with:
- Fluid layouts (percentages, flexible grids) stretch and shrink smoothly, but they do not *rearrange*. A fluid three-column row at phone width becomes three unreadably thin columns. Fluidity is part of responsiveness, not the whole of it.
- Adaptive layouts serve different fixed layouts per device — the server or JavaScript detects "phone" and loads a different design. That works, but it means maintaining several designs. Media queries give you the adaptive *effect* from a single design, which is why beginners start here.
The mental model to keep: your CSS describes the default layout, and media queries are conditional overrides — "but if the screen is narrow, do it this way instead."
What is the viewport meta tag — and what breaks without it?
Phones lie to websites about their width. A phone with a 390-pixel-wide screen tells CSS it is about 980 pixels wide, renders the page at that width, then zooms out so it all fits. This made old desktop-only sites usable on early smartphones — and it makes media queries silently not fire, because the browser thinks it has a wide screen.
The fix is one line in the <head> of every page you ever write:
<meta name="viewport" content="width=device-width, initial-scale=1">width=device-width tells the browser: report your *real* width. initial-scale=1 says: do not zoom out. With this line, a 390-pixel phone reports 390 pixels, and @media (max-width: 480px) fires exactly when it should.
Rule of thumb: if your media queries work when you resize a desktop browser but not on a real phone, the viewport meta tag is missing. It is the single most common "responsive design is broken" cause, and it is always this one line.
What is a media query?
A media query wraps ordinary CSS in a condition. The syntax:
@media (max-width: 768px) {
/* these styles apply only when the viewport is 768px wide or narrower */
.sidebar { display: none; }
}Read it as a sentence: "at media (screens) whose max width is 768 pixels, hide the sidebar." Everything inside the braces is normal CSS — selectors, properties, values. The query only decides *when* it applies.
The two directions:
| Query | Meaning | Use it when… |
|---|---|---|
@media (max-width: 768px) | screen is 768px or narrower | writing desktop-first: you designed wide, and adapt *down* |
@media (min-width: 769px) | screen is 769px or wider | writing mobile-first: you designed narrow, and adapt *up* |
Queries can combine conditions — @media (max-width: 768px) and (orientation: portrait) — and they can test more than width (hover, prefers-color-scheme, prefers-reduced-motion), but width carries 95% of beginner responsive work. Learn width first.
One more piece of the mechanism: the cascade still applies. A media query block does not automatically beat the styles above it — it wins because it comes *later* in the stylesheet with equal specificity. That is why ordering (covered in the worked example) matters.
Which breakpoints should a beginner use?
A breakpoint is the width where you add a media query. The honest answer: your breakpoints should be wherever your layout breaks. Resize the browser slowly; when the design starts looking wrong, that width is a breakpoint. No list of phone models needed.
That said, beginners benefit from a starting set instead of a blank page. A sensible trio that covers most layouts:
| Breakpoint | Roughly corresponds to | Typical use |
|---|---|---|
1024px | small laptops, landscape tablets | tighten multi-column areas |
768px | portrait tablets, large phones | collapse 3 columns to 2, simplify navigation |
480px | phones | single column, larger tap targets, trimmed content |
Do not memorise device widths (375, 390, 414, 360…). There are hundreds, they change yearly, and designing *to* them is the adaptive trap from section one. Three breakpoints where *your* content needs them will outlast any phone catalogue.
Worked example: a card grid that adapts
Here is the whole technique in one file. Save it as responsive-cards.html and open it in a browser — no tools, no build step, no JavaScript:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Responsive card grid</title>
<style>
.cards { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; }
.card { border: 1px solid #ccc; padding: 1rem; border-radius: 8px; }
@media (max-width: 768px) {
.cards { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 480px) {
.cards { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="cards">
<div class="card">Card one</div>
<div class="card">Card two</div>
<div class="card">Card three</div>
</div>
</body>
</html>Three things to trace through the cascade, in order:
- Base rule (no query): three equal columns. This is what every screen gets first.
max-width: 768px: on screens 768px or narrower, the grid becomes two columns. Note it is written *before* the 480px rule.max-width: 480px: on screens 480px or narrower, one column. Written *last*, so on a 400px phone — where *both* queries are true — the one-column rule wins, because it comes later with equal specificity.
Expected result, verified rule by rule against the specification:
- Wider than 768px: three columns side by side.
- 481–768px: two columns (the third card wraps to a second row).
- 480px and below: a single column of full-width cards.
That is the entire mechanism: base styles, then conditional overrides, ordered widest-first when you use max-width.

How do you test it without owning ten phones?
You do not need a device lab. Every major browser ships a responsive testing mode:
- Open the page and press F12 (or right-click → Inspect) to open developer tools.
- Click the device toolbar icon (the phone-and-tablet symbol, top-left of the dev tools panel).
- Pick a device preset from the dropdown — or drag the edge to any custom width and watch the layout snap between your breakpoints live.
What to check at each width: no horizontal scrollbar (content wider than the screen is the classic failure), text still readable without zooming, buttons and links comfortably tappable, and nothing important hidden or overlapping. Drag slowly from wide to narrow and note the exact widths where things look wrong — those are your future breakpoints, discovered rather than guessed.
One caution: the emulator is excellent for *layout*, but it is not a real phone. Before anything public, load the page on one actual phone at least once — real devices have rendering quirks (notch areas, browser chrome eating vertical space) that no emulator reproduces.
Mobile-first or desktop-first — which order should you write?
The example above is desktop-first: base styles target wide screens, and max-width queries adapt downward. It reads naturally if you designed on a laptop first. The alternative is mobile-first: base styles target the narrowest screens, and min-width queries adapt upward:
/* mobile-first version of the same grid */
.cards { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 481px) {
.cards { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 769px) {
.cards { grid-template-columns: 1fr 1fr 1fr; }
}Same three layouts, mirrored logic — and the ordering rule flips: with min-width, write the narrowest breakpoint first, widest last, so each wider rule wins where both are true.
Which should you choose? Mobile-first is the modern default, and worth adopting as a habit:
- It forces you to decide what matters most, because the small screen fits only the essentials — then wider screens *add*, rather than the desktop design being *carved down*.
- The base CSS (what every device downloads and parses) is the small, fast version; enhancements layer on for capable screens.
- It matches how most visitors arrive: the majority of web traffic is mobile, so the "default" experience should be the mobile one.
The worked example stays desktop-first purely for readability — most beginners sketch the wide layout first. Once the mechanism clicks, rewrite it mobile-first as the Try It exercise below.
What else changes on small screens besides layout?
Beginners often stop at "columns collapse" and ship a page that is technically responsive but miserable to use. The rest of the checklist:
- Type scales. A 48px desktop headline overwhelms a 360px screen; a 14px body looks fine on desktop but strains on phones held at arm's length. Media queries can adjust
font-size— or better, use fluid type (clamp()) so size interpolates instead of jumping. - Tap targets grow. Fingers are less precise than cursors. Navigation links, buttons and form controls need comfortable tap areas on touch screens — if your desktop nav uses 12px text links packed tightly, give the mobile version roomier spacing.
- Navigation transforms. A horizontal nav bar rarely survives 400px. The standard pattern: below a breakpoint, the links collapse behind a menu button. (Building the toggle needs a little JavaScript — a good follow-up project after this tutorial.)
- Content gets trimmed, not just squeezed. Some things make sense to hide or simplify on small screens — decorative sidebars, multi-column footers, dense data tables (which may need horizontal scrolling in a contained wrapper rather than breaking the page). Hiding is a tool, not a failure — but hide *decoration*, never the content the visitor came for.
Try it yourself
Using the worked-example file: 1. Move the breakpoints. Change 768px to 900px and 480px to 600px, reload, and drag the browser width slowly. Watch where each layout kicks in. This is how you learn that breakpoints are choices, not magic numbers. 2. Rewrite it mobile-first. Convert the stylesheet to the min-width version from the previous section (single column base, two columns at 481px, three at 769px). Verify all three layouts still appear at the same widths. 3. Adapt the type. Add a rule so the cards' text is 1.25rem on desktop but 1rem under 480px, and increase the card padding on phones. Small screens need breathing room, not just fewer columns.
Common mistakes
- Forgetting the viewport meta tag. Media queries work when you resize a desktop browser but "break" on a real phone — the phone is rendering at 980px and zooming out. Add
<meta name="viewport" content="width=device-width, initial-scale=1">to every page. - Breakpoints per phone model. Writing queries at 375px, 390px, 414px and 360px to chase specific phones. There are hundreds of widths; pick 2–3 breakpoints where *your layout* needs them instead.
- Wrong query order. With
max-width, the narrowest query must come last; withmin-width, the widest must come last. Reversed order means the wider rule wins where both apply, and the small-screen layout never appears. - Hiding content instead of adapting it. Reaching for
display: noneon everything that does not fit, until the mobile page is a hollow shell. Rearrange first, simplify second, hide decoration only — never the content the visitor came for. - Never testing on a real phone. The desktop device emulator covers layout, but touch behaviour, notch areas and browser chrome differ on hardware. Check one real phone before anything public.
Frequently asked questions
How many breakpoints do I need?
Start with two or three (the 1024 / 768 / 480 set from this tutorial is a fine default). Add more only when you find a width where the layout looks wrong. Most beginner projects never need more than three; a page with seven breakpoints is usually a sign the base layout was not flexible enough.
Are media queries enough, or do I need a framework like Bootstrap or Tailwind?
Media queries are enough to learn the mechanism — and you should learn it raw first, because frameworks are prebuilt media-query systems with class names on top. Once you can write the card-grid example from memory, a framework becomes a speed tool rather than a mystery.
What is the difference between responsive and adaptive design?
Responsive uses fluid grids plus media-query breakpoints, so one design serves every width. Adaptive serves distinct fixed layouts per device class (phone layout, tablet layout, desktop layout), chosen by detection. Responsive is one codebase adapting; adaptive is several designs selected. Media queries are the responsive tool.
Do media queries work in all browsers?
Width-based media queries have been universally supported for well over a decade — this is not a compatibility worry. If a query "doesn't work", the cause is almost always the missing viewport meta tag or a specificity/order mistake, not the browser.
Should I design mobile-first or desktop-first?
Learn both orders, then default to mobile-first: base styles for the small screen, min-width queries adding complexity upward. It forces content priority decisions early and matches where most visitors arrive from. The tutorial's example is desktop-first only because most beginners sketch wide first. ---
Follow the Frontend Developer Roadmap
Build modern, responsive websites and web apps with HTML, CSS, JavaScript and React. Free, step by step, at your pace.
View the Roadmap