Responsive Design and Media Queries: Mobile-First Breakpoints, Relative Units, and the Viewport Meta Tag
Responsive design rests on three pieces working together: the viewport meta tag, relative units, and min-width media queries. Learn how mobile-first breakpoints actually cascade, why em resolves differently inside a media query than in a rule, and how clamp() and fluid grids cut your breakpoint count — then check yourself with six practice questions.
Responsive design means building one HTML document that reshapes itself to fit any screen, and it rests on three pieces working together: the viewport meta tag, relative units, and media queries. Mobile-first is the strategy that ties them together — you write your base CSS for the narrowest screen, then use min-width media queries to add columns and spacing only once there is room for them.
The viewport meta tag comes first
Mobile browsers render pages into a virtual viewport that is wider than the screen — commonly around 980 CSS pixels — and then scale the whole result down to fit. Your breakpoints never fire, because as far as the browser is concerned the viewport really is 980px wide. One tag in the <head> fixes it:
<meta name="viewport" content="width=device-width, initial-scale=1">
width=device-width sets the layout viewport to the device's own width in CSS pixels instead of that wide default, and initial-scale=1 loads the page at 100% zoom. Steer clear of user-scalable=no or a restrictive maximum-scale: blocking pinch-zoom shuts out readers with low vision, and WCAG expects at least 2× scaling. Browsers increasingly override those values anyway — iOS has ignored user-scalable=no by default since iOS 10 — so writing them buys you nothing but a bad signal.
Relative units keep sizes flexible
A font size in px is fixed: it ignores the reader who has raised the default text size in their browser settings. (Browser zoom still scales pixels; the default-font-size preference does not.) Relative units respond to both. The ones you will reach for constantly:
em— resolves against the element's own computedfont-size, except when you are settingfont-sizeitself, where it resolves against the inherited font size.rem— resolves against the root element's font size (thehtmlelement), so it never compounds through nesting.%— resolves against the containing block, but which dimension depends on the property. Forpaddingandmarginit is always the containing block's inline size — its width in a horizontal writing mode — even on the top and bottom sides.vw/vh— 1% of the viewport's width / height.ch— the advance measure of the "0" glyph in the current font, useful for capping line length with something likemax-width: 65ch.
Writing mobile-first breakpoints
Base styles carry the single-column layout, and each min-width query layers on top of it:
.wrapper { display: grid; gap: 1rem; } /* one column */
@media (min-width: 40em) {
.wrapper { grid-template-columns: 1fr 1fr; } /* two columns */
}
Pick breakpoints where your content starts to look wrong, not at the pixel width of any particular phone. And note that the width media feature describes the viewport, not the device's screen — the old device-width feature that did test the screen is deprecated.
Fluid layouts need fewer breakpoints than you think
Media queries are a tool, not a requirement. img { max-width: 100%; height: auto; } keeps images inside their container. grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)) reflows on its own. font-size: clamp(1.5rem, 4vw, 3rem) scales type between a floor and a ceiling with no query at all. Reach for a breakpoint only when fluid CSS cannot express the change. For the full topic map, see the WGU D276 Web Development Foundations study guide.
Practice: Responsive Design Media Queries
-
You are converting a page to a mobile-first approach. Which arrangement of CSS actually follows the mobile-first pattern?
- Base styles lay out a single column, and @media (min-width: 45em) switches to two columns
- Base styles lay out two columns, and @media (max-width: 45em) collapses them to one column
- Base styles lay out a single column, and @media (max-width: 45em) switches to two columns
- @media (min-width: 45em) sets a single column and @media (max-width: 45em) sets two columns, with no unconditional base rules
Show answer & explanation
Correct answer: Base styles lay out a single column, and @media (min-width: 45em) switches to two columns. Mobile-first means the unconditional base styles describe the narrow-screen layout, and min-width queries progressively add complexity as the viewport grows. The two-column base with a max-width query is the mirror image — it is desktop-first, which works but is not what was asked for. The third option is backwards on both counts, and the fourth throws away the base layout that applies when no query matches.
-
What does width=device-width in <meta name="viewport" content="width=device-width, initial-scale=1"> actually do?
- It makes one CSS pixel equal exactly one physical device pixel on the screen
- It sets the layout viewport's width to the device's own width in CSS pixels, replacing the browser's wider default virtual viewport
- It sets the CSS width of the body element to match the screen size
- It stops the user from pinch-zooming so your layout stays at the size you designed
Show answer & explanation
Correct answer: It sets the layout viewport's width to the device's own width in CSS pixels, replacing the browser's wider default virtual viewport. Mobile browsers lay pages out in a virtual viewport wider than the screen (commonly around 980px) and scale the rendered result down to fit, which makes min-width breakpoints behave as if every phone were a desktop. width=device-width replaces that default with the device's own width in CSS pixels. It does not touch the device-pixel ratio, does not style the body element, and does not disable zoom — that would be user-scalable=no, which you should avoid because it blocks readers who need to magnify text.
-
A stylesheet contains html { font-size: 20px; } and a breakpoint written as @media (min-width: 40em). At what viewport width does that media query start to match, assuming the browser's default font size of 16px has not been changed by the user?
- 800px, because 40 x 20px matches the root font-size you declared
- 640px, because relative units in a media query resolve against the initial font size, not your declarations
- It depends on the font-size of whichever element the rules inside the query target
- 40px, because em in a media query is treated as a raw pixel count
Show answer & explanation
Correct answer: 640px, because relative units in a media query resolve against the initial font size, not your declarations. The Media Queries specification states that relative length units in media queries are based on the initial value, so units are never based on the results of declarations — the em reflects the user agent or user's preferred font size, not your html { font-size: 20px } rule. With a 16px default, 40em is 640px. This is exactly why em breakpoints respect a reader who has raised their browser's default text size, and why rem and em behave identically inside a media query.
-
A block-level element in a normal horizontal writing mode sits inside a containing block that is 600px wide and 200px tall. You write padding-top: 50% on that element. How tall is the top padding?
- 100px — half the containing block's height
- 300px — half the containing block's width
- 0, because percentage values are invalid on vertical padding
- It depends on the element's own content height
Show answer & explanation
Correct answer: 300px — half the containing block's width. Percentage values for padding (and margin) resolve against the inline size of the containing block — its width in a horizontal writing mode — and that includes padding-top and padding-bottom. That gives 50% of 600px, or 300px, not 50% of the 200px height. This surprises people constantly, but it is the behavior that makes the classic aspect-ratio padding trick work, since a width-based percentage produces a height that stays proportional as the box resizes.
-
With the root font-size at the browser default of 16px, an element has font-size: clamp(1.5rem, 4vw, 3rem). What is its computed font size in a viewport 400px wide?
- 16px, since 4vw of 400px is 16px and that is the preferred value
- 24px, because the preferred value falls below the minimum, so the minimum is used
- 48px, because narrow viewports always take the third value
- 20px, the midpoint between the minimum and the preferred value
Show answer & explanation
Correct answer: 24px, because the preferred value falls below the minimum, so the minimum is used. clamp(min, preferred, max) resolves as max(min, min(preferred, max)). Here 4vw of a 400px viewport is 16px, which is smaller than the 1.5rem (24px) minimum, so the minimum wins and the text renders at 24px. That floor is the entire point of clamp() for fluid typography — it stops viewport-relative text from shrinking into illegibility on small screens — and the 3rem ceiling would only take over on a very wide viewport.
-
Given the CSS below, what padding does .card have when the viewport is 1200px wide (root font-size 16px)? .card { padding: 1rem; } @media (min-width: 60em) { .card { padding: 3rem; } } @media (min-width: 40em) { .card { padding: 2rem; } }
- 3rem, because the narrower-matching query is the more specific match
- 2rem, because both queries match and the later rule wins on source order
- 1rem, because two conflicting queries cancel each other out
- 5rem, because the padding from both matching queries is added together
Show answer & explanation
Correct answer: 2rem, because both queries match and the later rule wins on source order. At 1200px both min-width conditions are true (60em is 960px, 40em is 640px), so both declarations apply and the cascade has to break the tie. A media query adds nothing to specificity, and these selectors are identical, so the last one in source order wins — 2rem. This is the classic mobile-first ordering bug: write your min-width breakpoints from smallest to largest so the wider query comes last and can override the narrower one.
A worked example: why breakpoint order matters
Media queries feel like conditionals, so people assume the "best match" wins. It does not. A media query is a conditional group rule: it gates whether a rule is in play, and contributes nothing to specificity. When two gated rules with identical selectors are both open, the cascade falls through to source order.
/* Correct mobile-first order: small to large */
.card { padding: 1rem; }
@media (min-width: 40em) { .card { padding: 2rem; } }
@media (min-width: 60em) { .card { padding: 3rem; } }
At 1200px both queries match, but the 60em block comes last, so you get 3rem. Flip those two blocks and the 60em breakpoint silently stops working — no error, no warning, just a layout that refuses to grow past its medium size. If you write desktop-first with max-width, the rule reverses: order those blocks largest to smallest.
Mistakes people actually make
- Omitting the viewport meta tag. Every breakpoint you wrote is dead on phones, and the whole page renders zoomed out. This is the single most common reason a "responsive" page is not.
- Setting
html { font-size: 62.5% }and expecting media queries to follow. They will not. Inside a media query,emresolves against the initial font size — the user agent or user preference — so your root declaration has no effect there. Yourremsizes shrink; your breakpoints do not move. - Using
100vwfor a full-width block. Viewport units are relative to the viewport including the space taken by a classic scrollbar, sowidth: 100vwon a vertically scrolling page overflows by the scrollbar's width and produces a horizontal scrollbar. Usewidth: 100%on a block-level element instead. (Switching todvwdoes not help — the dynamic viewport units address the collapsing mobile toolbar, not the scrollbar.) - Chaining
emsizes. Nested elements each multiply the last, so0.9emthree levels deep lands at about 0.73 of the original. Useremwhen you want a stable size andemwhen you genuinely want to scale with the local text. - Picking breakpoints from a device list. Screen sizes change every year; your content's comfortable line length does not. Widen the browser until the layout looks awkward — that is your breakpoint.
Reasoning through the tricky cases
When a percentage confuses you, ask what its reference is, because it varies by property: padding and margin reference the containing block's inline size — its width in a horizontal writing mode — even on the top and bottom sides, while height: 50% references the containing block's height. When a fluid value confuses you, expand clamp(a, b, c) into max(a, min(b, c)) and evaluate it literally with real numbers.
Before reaching for a query at all, ask whether flex-wrap, minmax() with auto-fit, or clamp() already handles it — the fewer breakpoints you own, the fewer you can break. Ready to test yourself further? Work through the D276 practice questions.
Want someone to walk you through this?
Book 1-on-1 prep for WGU D276 — original coaching, never exam content.
Stuck on this topic? WhatsApp us on +1 646 980 4914.
Working through the whole course? Read the full WGU D276 study guide, or see every WGU D276 practice topic.