← Front-End Developer — all chapters  ·  Kelick Tech Hub

Chapter 12 — Responsive Design and Media Queries

Section 1 — What responsive design means

Responsive design means building one web page that adapts itself to the screen it is shown on, instead of building a separate page for every kind of device. The same HTML document, the same words and the same pictures can appear as a single comfortable column on a phone, as two columns on a tablet, and as three columns on a wide laptop screen. What changes is the arrangement, the size of type and images, and sometimes which supporting details are shown first. What does not change is the content itself: the visitor still gets the same article, the same product, and the same actions, however they arrive.

This idea matters because you cannot know, when you write the code, what device will open your page. A visitor might use an old phone with a narrow screen, a new phone held sideways, a laptop, a large office monitor, or a television browser. In the early web, designers often built a page for one desktop size and hoped for the best everywhere else. That hope broke as phones became the main way many people reach the web. Responsive design replaces hope with a plan: the layout flexes, with clear rules for each size.

A useful mental picture is water poured into different containers. Water does not need a different recipe for a glass, a jug, and a bath; it takes the shape of whatever holds it. A responsive page should behave in a similar way. Its columns should narrow and stack, its images should shrink, and its navigation should rearrange, all without the visitor having to pinch, zoom, or scroll sideways to read a sentence. When that happens, the design has done its job, and the visitor can focus on the content.

It is important not to confuse responsive design with simply making everything smaller. Shrinking a desktop page until it fits a phone screen produces tiny text and buttons too small to tap. True responsiveness rearranges the design for the new shape. A sidebar that sat beside an article on a desktop might move below it on a phone, where it is still available but no longer competes for the narrow width. A row of four cards might become two rows of two, and then a single column. The priorities change with the space, even though the information stays the same.

Responsive design is also not the same as having a separate mobile website, such as a different address for phone users. That older approach meant maintaining two sites, and visitors often landed on the wrong one. A responsive site has one address, one set of content, and one codebase, which makes it easier to keep up to date and easier for search engines and sharing to handle. When you update a paragraph, every visitor sees the update, whatever their screen.

Finally, responsive design is a habit, not a single trick you add at the end. It shapes choices from the first stylesheet onwards: fluid widths instead of rigid ones, flexible images, relative type sizes, and layouts built from flexbox and grid rather than fixed pixel boxes. The rest of this chapter teaches those tools one at a time, but they all serve this one idea: one page, many screens, no visitor left struggling.

Check: In plain words, what changes in a responsive page, and what stays the same?

Section 2 — Why screens differ so much

Screens differ in far more than just width, and understanding those differences explains why a single fixed layout cannot serve everyone. A phone screen is narrow, usually held in one hand, and operated by a thumb that covers part of the display as it taps. A tablet is wider and often held with two hands, but still touched rather than clicked. A laptop has a keyboard, a precise mouse pointer, and a screen the user sits further away from. A desktop monitor may be very wide, and a television is wider still, viewed from across a room. Each of these is a different physical situation, not just a different number of pixels.

Width is the most obvious difference, and it directly controls how much content can sit side by side. On a 360-pixel-wide phone, two columns of text would each be so narrow that only a few words would fit per line, making reading slow and tiring. On a 1920-pixel monitor, a single column stretched to the full width would produce lines so long that the eye loses its place moving from the end of one line to the start of the next. Good layout therefore changes with width: stacking where space is scarce, and using columns and limits where space is plentiful.

Height matters too, although beginners often forget it. A phone in portrait orientation is tall and narrow, so visitors scroll a long way through a page, while the same phone turned sideways is short and wide, so a tall hero section can swallow the whole first screen. A laptop window may also be resized to half the screen while the user works beside another program. A design that assumes a fixed height, for example by forcing a section to fill exactly the viewport, will break in these everyday situations.

Input method changes what a design must do. A mouse can hover over a menu to reveal it, can click a tiny link precisely, and can right-click for more options. A finger cannot hover, cannot click as precisely, and covers what it touches, so menus must open on tap, targets must be larger, and important controls must not sit so close together that a thumb hits the wrong one. A design that only works with a hover will quietly exclude every touch visitor.

Connection and context differ as well. A phone visitor may be on a slow mobile network, standing on a bus, looking for one fact quickly. A desktop visitor may be on fast broadband, sitting down to compare options in detail. Both deserve the same content, but the phone visitor is punished far more by huge images, heavy scripts, and layouts that demand patience. Responsiveness therefore includes performance: sending appropriate image sizes and not wasting a small device's time and data.

The lesson is that "the user" is not one person on one screen. It is many people, in many places, on many devices, and your page must meet them where they are. Once you accept that variety as normal rather than exceptional, responsive techniques stop feeling like extra work and start feeling like basic craftsmanship.

Check: Why is a single fixed layout a poor fit for the modern web?

Section 3 — The viewport meta tag

The viewport meta tag is a small line of HTML that has an outsized effect on mobile browsers, and it belongs near the top of every page you build. It looks like this:

<meta name="viewport" content="width=device-width, initial-scale=1">

To understand why it matters, you need to know what mobile browsers did before it existed. Early phone browsers faced pages designed only for desktop monitors. If they had shown such a page at its true size, the visitor would have seen only a small corner of it. So browsers adopted a compromise: they pretended the screen was about 980 pixels wide, laid the page out at that width, and then shrank the whole result down to fit the phone screen. The visitor could then pinch and zoom to read parts of it, but nothing was designed for the phone itself.

That compromise still happens today if you leave the viewport tag out. Your careful responsive CSS may be completely correct, and yet the phone will shrink the desktop layout into a tiny, unreadable strip, because the browser never told your CSS the true screen width. Media queries based on width will also be measured against the pretend width rather than the real one, so a query meant for phones may never trigger. Many beginners debug their CSS for hours when the real problem is one missing line in the head.

The tag's two values are easy to read once you know them. width=device-width tells the browser that the viewport — the visible area your CSS lays out in — should equal the device's actual width in CSS pixels, not a pretend desktop width. initial-scale=1 sets the starting zoom level to 100%, so the page is neither magnified nor shrunk when it first loads. Together they say, in effect, "trust the real screen size, and show the page at its natural size."

There are other viewport values you may see in old code, and one you must avoid. maximum-scale=1 or user-scalable=no would stop visitors from zooming at all. That might look tidy to a designer, but it blocks people with low vision who need to magnify text, and it fails accessibility expectations. Never disable zoom to make a layout look neat; fix the layout instead so that zooming works.

A good habit is to make the viewport tag one of the first things you type in any new HTML file, right after the character encoding tag and before the title. Test it by opening your page on a phone or in device mode: if the text is readable without pinching, the tag is doing its job. If everything looks miniature, check the head first, before touching a single line of CSS.

Check: What does the viewport meta tag tell a mobile browser to do?

Section 4 — Fixed widths versus fluid widths

A fixed width is a width that never changes, whatever the screen. A fluid width is a width expressed as a share of the available space, so it grows and shrinks with its container. The difference between them is the difference between a rigid box and a stretchable one, and choosing the right kind in the right place is one of the first responsive skills.

Consider a main content box set to width: 960px;. On a laptop screen wider than 960 pixels, it sits comfortably, perhaps centred with margins on either side. On a phone screen 360 pixels wide, however, the same box is nearly three times wider than the screen. The browser must either cut it off or force the whole page to scroll sideways, and neither is acceptable reading experience. The visitor has to drag the page left and right just to finish a sentence. That is the classic fixed-width failure, and it happens the moment a screen narrower than the fixed size appears.

Now consider the same box set to width: 90%;. On the laptop it takes 90% of its parent, leaving a small margin. On the phone it takes 90% of the phone screen, which is a comfortable reading width. On a tablet it takes 90% of the tablet. One rule serves all three, because the width is defined relative to the space available rather than as an absolute number. This is why fluid widths are the starting point of responsive layout: they adapt automatically, without needing a media query for every possible screen.

Fluid does not mean unlimited, however. A box at 90% on a very wide monitor could stretch to an enormous width, producing lines of text too long to read comfortably. That is why fluid widths are usually paired with a maximum, which you will meet in the next section: grow freely, but stop at a sensible limit. Likewise, a fluid box can become too narrow on a tiny screen, so a minimum width is sometimes needed for components like buttons or cards that must keep a usable size.

Fixed widths still have a place, but it is a small one. Borders, small icons, and details that genuinely never need to scale — a 1-pixel border, a 24-pixel icon — are fine as fixed pixels. What should not be fixed is the structure of the page: containers, columns, and main content areas. If you catch yourself setting a column to an exact pixel width, pause and ask whether a percentage, a flexible grid track, or a maximum width would serve better. In most cases, it will.

A practical test helps: resize your browser window from wide to narrow while watching each major box. If a box holds its width and pushes the page sideways, it is too fixed. If it narrows gracefully and its content reflows, it is fluid enough. Learning to see that difference is learning to see responsiveness itself.

Check: Which kind of width overflows a phone screen, and why?

Section 5 — Percentages in layout

Percentages are one of the simplest responsive tools, because they describe a relationship rather than an absolute size. When you write width: 50%; on an element, you are not saying "be this many pixels wide." You are saying "be half as wide as your parent." If the parent grows, the child grows with it; if the parent shrinks, the child shrinks too. That relationship holds at every screen size, which is why percentages adapt without extra code.

It is worth being precise about what a percentage is measured against, because different properties use different references. For width, a percentage is measured against the width of the containing block, usually the parent element's content box. For height, a percentage is measured against the parent's height, but only if that height is itself defined — a common source of confusion when a percentage height appears to do nothing because the parent's height depends on its content. For padding and margin, a percentage is measured against the parent's width, even for top and bottom padding, which surprises many beginners but is consistent once you know it.

A concrete layout example makes this clear. Imagine a container with two boxes inside it, each set to width: 50%; and placed side by side. On a desktop the container might be 1000 pixels wide, so each box is 500 pixels. On a tablet at 700 pixels, each box becomes 350 pixels. On a phone at 360 pixels, each becomes 180 pixels. The boxes have changed size three times, yet you wrote only one rule. If 180 pixels turns out to be too narrow for the content, that is the moment for a media query to stack the boxes instead — but until that point, percentages have handled everything for free.

Percentages also combine well with other techniques. A sidebar at 30% and a main area at 70% will keep their proportions at any width, and adding box-sizing: border-box; ensures that padding and borders are counted inside those percentages rather than added on top of them. Without border-box sizing, a box at 50% plus 20 pixels of padding becomes wider than 50%, and two such boxes no longer fit side by side. Many stylesheets therefore begin with a rule applying border-box sizing to all elements, so percentages behave predictably.

There are limits. Percentages alone cannot say "never narrower than this" or "never wider than that," which is why they are paired with min-width and max-width. They also cannot create gutters between columns by themselves; that job belongs to flexbox gaps or grid gaps. But as a foundation, percentages teach the central responsive lesson: describe sizes in relation to their surroundings, and the layout will take care of many screen sizes on its own.

Check: If a box is width: 50%;, what is the 50% measured against?

Section 6 — A centred container with max-width

One of the most used patterns in responsive design is a container that fills a small screen but stops growing on a very wide one. It is written like this:

.container {
  width: 90%;
  max-width: 1100px;
  margin: 0 auto;
}

Each part of that rule has a job. width: 90% makes the container fluid: on any screen it takes nine tenths of the available width, leaving a small breathing margin at each side. That margin matters on a phone, where text pressed hard against the edge of the glass is tiring to read and easy to mis-tap. On a tablet the same 90% gives a comfortably wide reading area. So far, the container behaves like the fluid boxes in the previous section.

max-width: 1100px then adds a ceiling. Once the screen is wide enough that 90% would exceed 1100 pixels, the container stops growing and stays at 1100. This protects readability on large monitors. Without a ceiling, a paragraph on a wide screen would stretch into a single very long line, and the reader's eye would struggle to find the start of the next line after finishing one. Typographers have long advised keeping line lengths in a comfortable range, and a max-width container is the simplest way to enforce that on the web. The exact ceiling is a design choice — 700 pixels suits a text-heavy article, 1100 suits a general site, 1280 suits a dashboard — but the principle is the same.

margin: 0 auto centres the container once it stops growing. The top and bottom margins are zero, while the left and right margins are set to auto, which the browser splits equally between the two sides. The result is a container sitting in the middle of a wide screen with equal empty space on either side, rather than hugging the left edge while a large blank area sits on the right. Centring only becomes visible once the max-width kicks in; below that width the container fills 90% and the margins are simply the remaining 10% shared between the sides.

This pattern is usually applied to a wrapper element that holds the page's main content, while the page background, header, or footer may stretch full width behind it. That combination — full-width colour bands with a centred, limited content column inside — is the look of a great many professional sites, and it is achieved with this one short rule.

There are useful variations. A narrower container, such as max-width: 700px, suits long-form reading. A wider one suits image galleries. Some designs use different max-widths for different sections, or add padding inside the container so content never touches its edge. What matters is the idea: fluid below the limit, capped above it, centred when capped. Master that, and a large part of responsive layout is already handled.

Check: What do width: 90% and max-width: 1100px each do in that container rule?

Section 7 — Relative units: em and rem

Pixels are absolute units: one pixel is one pixel, whatever the visitor's settings. Relative units, by contrast, are measured against something else, so they adapt when that something else changes. The two most important relative units for text and spacing are em and rem, and confusing them is a common beginner error, so it is worth learning the difference precisely.

One rem is the font size of the root element, the <html> element. Browsers default to 16 pixels for that size, so 1rem is normally 16 pixels, 2rem is 32 pixels, and 0.5rem is 8 pixels. If a visitor has increased their browser's default font size because they need larger text — a common accessibility setting — the root size grows, and every rem value in the stylesheet grows with it. A layout built in rem therefore respects the visitor's preference in a way that a layout built only in pixels does not. That is a strong reason to prefer rem for font sizes, padding, and margins.

One em is the font size of the element itself, or of its parent if the element's own size is not set. This makes em useful inside a component that should scale as a whole: if a button's font size grows, its padding in em grows too, keeping the button's proportions. But em can also compound unexpectedly. If a list is nested inside another list, and both use em for their font sizes, the inner list's text is scaled relative to an already scaled size, and the result can be larger or smaller than intended. This nesting trap is the main reason many developers use rem for most sizing and reserve em for deliberately local scaling.

A worked example helps. Suppose the root font size is 16 pixels. A heading set to font-size: 2rem renders at 32 pixels. A paragraph set to font-size: 1rem renders at 16 pixels. A button with font-size: 1rem and padding: 0.5em 1em gets 8 pixels of vertical padding and 16 pixels of horizontal padding, because em here refers to the button's own 16-pixel font size. If the visitor raises their default font size to 20 pixels, all three scale up together, and the proportions stay intact.

A practical approach is to set most font sizes and spacing in rem, use em sparingly inside self-contained components, and keep pixels for things that should never scale, such as a 1-pixel border. You can also change the root size at a breakpoint — for example, a slightly larger root size on wide screens — and watch the whole rem-based layout breathe outward in step. That single change, applied thoughtfully, is often more elegant than adjusting dozens of individual pixel values.

A final practical tip: when you are unsure whether to use em or rem, ask whether the size should follow the component or the page. A badge inside a button should follow the button, so em makes sense; a page heading should follow the reader's overall setting, so rem is safer. That single question resolves most cases, and it keeps your stylesheet consistent without a rigid rule that breaks in edge cases.

Check: What is the difference between em and rem?

Section 8 — Viewport units: vw and vh

Viewport units measure against the browser window itself rather than against a parent element or the root font size. 1vw is 1% of the viewport's width, and 1vh is 1% of its height. So on a window 1200 pixels wide, 10vw is 120 pixels; on a phone 360 pixels wide, 10vw is 36 pixels. The value follows the window, not the content, which makes viewport units powerful for full-screen sections and dangerous for ordinary text.

The most sensible use is a section that should relate to the screen itself. A hero banner set to width: 100vw spans the full window width, even if its parent is narrower. A heading that should feel big on a desktop and modest on a phone can use a viewport-based size as part of a clamp() expression, which you will meet later in this chapter. In those roles, viewport units express an idea that percentages cannot: "size this in relation to the window, not to the nearest box."

The danger comes from using viewport units alone for body text. Text sized at, say, 2vw will be 24 pixels on a 1200-pixel screen, which is readable, but only about 7 pixels on a 360-pixel phone, which is not. The text shrinks below legibility precisely where the visitor has the least room and the most need for clarity. Viewport-sized text also ignores the visitor's chosen default font size, because it is tied to the window rather than to their preference. For those two reasons, body text should be sized in rem, with viewport units used only inside a clamp() that guarantees a minimum.

Height units have their own trap, covered in more detail later in this chapter: on many mobile browsers, 100vh does not quite mean the visible height, because the browser's address bar appears and disappears. Newer units such as dvh address that, but the general lesson stands: test viewport heights on a real phone, not only in a desktop preview.

There are also vmin and vmax, which use the smaller or larger of the viewport's width and height. vmin is handy for a square that must fit on screen in either orientation: width: 90vmin; height: 90vmin; gives a square that fits whether the phone is portrait or landscape. These are specialised tools, but they illustrate the same principle: viewport units answer the question "how big is the window?", and you should reach for them only when that is genuinely the question you are asking.

Viewport units also deserve a note about accessibility and user settings. Because they follow the window rather than the visitor's font preference, a design that relies heavily on vw for text can silently override a reader's chosen size. That is why the safest pattern pairs a viewport value with a rem floor inside clamp(), so the window influences the size but never overrides the reader's minimum. Test that combination with an enlarged default font size to confirm it behaves.

Check: Why should body text not be sized in vw alone?

Section 9 — What a media query is

A media query is a conditional rule in CSS: a set of styles that only applies when a stated condition about the viewing environment is true. In plain language, it lets your stylesheet say "if the screen is like this, then lay things out like that; otherwise, carry on as before." Without media queries, a stylesheet would have only one answer for every screen. With them, it can have several answers, each chosen by the situation.

The most common condition is width, but the idea is broader. A media query can ask about height, orientation, whether the device is a screen or a printer, whether the user prefers a dark colour scheme, or whether they prefer reduced motion. Each of those questions lets the design adapt to something the author cannot know in advance. That adaptability is the heart of responsive design: instead of assuming one environment, the stylesheet checks its environment and responds.

Crucially, a media query does not replace your base styles. Think of the base styles as the default answer, written for the most common or most constrained case — in mobile-first design, the phone. Media queries then layer adjustments on top of that default. If a visitor's browser does not understand a particular query, or if the condition is false, the base styles still produce a usable page. That fallback quality is important: a page that only works when a media query matches is fragile, while a page with a solid base and thoughtful adjustments is robust.

It helps to read a media query as a sentence. @media (min-width: 700px) reads as "when the viewport is at least 700 pixels wide." The styles inside then describe what changes in that situation. Often only one or two properties change — a flex direction, a number of grid columns, a padding value — while everything else stays as the base defined it. Beginners sometimes copy an entire component's styles into a media query, but that duplication is unnecessary and hard to maintain. Change only what needs to change, and let the cascade carry the rest.

Media queries also respect the cascade and specificity like any other CSS rule. A rule inside a media query does not automatically beat a rule outside it; if both apply and have equal specificity, the one that appears later in the stylesheet wins. This is why media queries are usually placed after the base styles for the component they adjust, so that their changes take effect when their condition is true.

It is also worth noting that media queries do not require JavaScript and do not need any special setup beyond a stylesheet. The browser evaluates them continuously, so resizing a window or rotating a phone re-evaluates the conditions immediately and applies or removes the matching styles without a page reload. That live re-evaluation is why dragging a browser window narrower produces a smooth, instant change in layout, and why media queries feel like a natural part of CSS rather than an add-on.

Check: What question does a media query ask before its styles apply?

Section 10 — Media query syntax

The syntax of a media query is short, but every character matters, so it is worth learning it exactly. A basic example looks like this:

@media (min-width: 700px) {
  .cards {
    flex-direction: row;
  }
}

Read it from the outside in. @media announces that what follows is a media query — a rule about the medium and its features. The condition, (min-width: 700px), sits in parentheses. It states a feature, min-width, and a value, 700px. The opening brace begins the block of styles that apply when the condition is true, and the closing brace ends it. Inside, you write ordinary CSS rules exactly as you would anywhere else.

The most common mistake is a missing parenthesis or brace, which can silently swallow the rest of the stylesheet or make the query do nothing. Another common mistake is confusing min-width and max-width. Remember it this way: min-width: 700px means the viewport must be at least 700 pixels — it is a minimum requirement, so it matches wide screens. max-width: 700px means the viewport must be at most 700 pixels — a maximum, so it matches narrow screens. Saying the words "at least" and "at most" aloud while you type will catch many errors.

Conditions can be combined. The keyword and joins two conditions that must both be true, for example @media (min-width: 600px) and (orientation: landscape). Commas act as "or": @media (max-width: 600px), print applies to narrow screens or to printing. You can also specify a media type, such as screen or print, although modern practice often omits the type and tests features directly, since the query is usually intended for screens anyway. A print stylesheet, which you might meet in a later chapter, is the main case where naming the type matters.

Placement in the stylesheet matters for the reason given in the previous section: the cascade. Put a component's media queries after its base styles, or at least after any rules they are meant to override with equal specificity. Many developers keep each media query immediately below the component it adjusts, which makes the relationship obvious to the next person reading the file. Others gather all queries at the end of the stylesheet. Either can work, but mixing the two approaches randomly makes maintenance harder.

Finally, remember that a media query is only as good as the condition it tests. A query that triggers at a width where your design still looks fine is wasted, and one that triggers too late leaves a broken interval. The next section explains how to choose those trigger points from your own design rather than from a list.

One more syntax detail saves confusion later: a media query can also use the keyword not, which inverts a condition, and only, which older browsers use to ignore queries they do not understand. Beginners rarely need either, but recognising them when reading older stylesheets prevents misreading a rule. In modern code, plain conditions joined by and, or separated by commas, cover almost every responsive need, and keeping to those forms keeps your queries readable.

Check: Read the example media query aloud in plain English.

Section 11 — Breakpoints are decisions, not devices

A breakpoint is the width at which a layout stops working well and needs to change its arrangement. It is a decision you make about your own design, not a fact about a particular phone or tablet. That distinction matters, because beginners often search the web for a list of "standard breakpoints" — the widths of popular devices — and paste them into their stylesheet whether or not their design needs them. The result is a stylesheet full of queries that trigger at widths where nothing was actually broken, and sometimes missing a query at the width where their own layout does break.

A better method is to discover breakpoints by watching your design. Open your page in a browser, drag the window slowly narrower, and pay attention. At some width the navigation starts to wrap awkwardly. At another width the cards become too narrow to read. At another, a heading wraps in an ugly place or an image crowds its caption. Each of those moments is a breakpoint asking to be recorded. Write down the approximate width, then write a media query at that width that fixes that specific problem — perhaps by stacking the navigation, reducing the number of columns, or shortening a heading's size. The query exists because the design needed it, and its purpose is obvious to anyone reading the code.

This approach has a practical advantage: it keeps the number of breakpoints small. Most pages need only two or three, because most layouts only break in a few ways. A page with eight breakpoints is usually a sign that the base layout was too rigid to begin with, and that flexible techniques — fluid widths, wrapping flexbox, auto-fitting grids — could have handled many of those sizes without any query at all. Media queries should be the exception that fixes what flexible layout cannot, not the main mechanism for every size.

Breakpoints also differ between projects, because designs differ. A text-heavy blog might break at 600 pixels, where its sidebar crowds the article. A photo gallery might break at 900 pixels, where four columns become too narrow for the images. A dashboard might break at several widths as its panels rearrange. Copying another project's breakpoints would miss all of that. Your breakpoints should be named in comments by what they do — "navigation collapses," "cards go two-up" — rather than by a device name, because devices change every year while your design's breaking points are visible right now.

Finally, remember that a breakpoint is not a wall between "mobile" and "desktop." Screens exist at every width in between, including tablets, small laptops, split-screen windows, and phones turned sideways. A good breakpoint makes the layout work on both sides of it and in the transition between them. Test a little either side of each breakpoint, not only exactly at it, and you will catch awkward in-between states before your visitors do.

Check: How do you find a good breakpoint for your own layout?

Section 12 — Mobile-first design

Mobile-first design means writing your base styles for a small screen first, and then adding media queries that enhance the layout as the screen grows larger. The phone layout is the default, not a version squeezed in afterwards. That ordering — small first, large later — shapes the whole stylesheet, because the base styles describe the simplest, most essential arrangement, and each min-width query adds something only when there is room for it.

The reason mobile-first is recommended for new projects is partly practical and partly about priorities. Practically, a phone is the most constrained environment: narrow width, touch input, possibly slow connection. If a design works there, adding room usually makes it easier, not harder. The reverse is not true. A design built for a wide screen and then shrunk often loses things along the way — sidebars crammed in, text reduced, features hidden — and the phone version can feel like a cut-down afterthought. Starting small forces the essential content to be right before decoration is added.

There is also a discipline benefit. A small screen forces choices about what matters most. You cannot show everything at once on a phone, so you must decide the order: the headline first, then the key action, then supporting detail. Those decisions improve the design at every size, because a page whose priorities are clear on a phone is usually clearer on a desktop too. Desktop designs that never faced that discipline often show everything at equal prominence, which is another way of showing nothing prominently.

In code, mobile-first looks like this. The base stylesheet stacks content in a single column, uses full-width buttons, and keeps padding modest. Then a query such as @media (min-width: 700px) arranges two columns, and another at 1100 pixels adds a third or widens the container. Each query uses min-width, meaning "this wide or wider," so styles accumulate as the screen grows. A browser that does not understand media queries at all still gets the usable single-column layout, which is a useful safety net for very old or limited browsers.

Mobile-first does not mean "mobile only" or "ignore desktops." It means the desktop layout is an enhancement of a working small-screen design, built deliberately, with its own queries and its own testing. The desktop visitor still gets columns, sidebars, and larger type — they simply arrive as additions to a solid foundation rather than as the foundation itself. When you adopt that order, you will find your stylesheets are shorter, your overrides fewer, and your phone layout stronger.

Mobile-first also simplifies testing, because the base layout is the one every visitor gets, including visitors on browsers that do not support media queries. You can test that base thoroughly on a phone, then test each enhancement at its breakpoint, knowing that a failure in an enhancement degrades to a working page rather than to nothing. That graceful degradation is a quiet strength of the approach, and it is one reason teams adopt it even for sites whose visitors are mostly on desktops.

Check: In mobile-first CSS, do the base styles describe a phone or a desktop?

Section 13 — Desktop-first, and why it is less common now

Desktop-first design is the reverse of mobile-first: the base styles describe a wide, desktop layout, and media queries with max-width then undo or shrink parts of that layout for smaller screens. For many years this was the normal way to work, because most visitors did use desktops, and phones were an exception to accommodate afterwards. Today the balance has shifted, and desktop-first is now the less common choice for new projects, though it is still worth understanding.

The logic of desktop-first is straightforward. You build the full layout first — multiple columns, a horizontal navigation bar, a sidebar, generous spacing — and then, at each smaller width, you ask what must change. At 1000 pixels the sidebar might narrow. At 700 pixels it might move below the content. At 400 pixels the navigation might collapse into a menu button. Each step uses max-width, meaning "this wide or narrower," so the adjustments apply as the screen shrinks. For a designer thinking in desktop terms, this sequence feels natural.

The drawback is the amount of undoing involved. A desktop layout contains many assumptions — that there is room for three columns, that a menu fits in one row, that an image can sit beside text — and each of those assumptions must be revisited and reversed for small screens. The stylesheet grows with overrides, and the phone layout can end up defined largely by what was removed rather than by what was designed. It is easy, in that process, to forget something: a fixed width left in place, a hover-only menu never replaced, a font size never reduced. The phone version then feels like a desktop page with pieces missing, which is exactly what visitors notice.

Desktop-first still has a legitimate use: adapting an existing desktop site that already works and cannot be rebuilt from scratch. In that situation, adding max-width queries is a pragmatic way to make the site usable on phones without rewriting everything. It is a rescue strategy, not a design ideal. If you inherit such a project, desktop-first queries are a sensible first step, and you can move components to mobile-first as you rebuild them.

For a new project, however, the recommendation stands: start small and enhance upwards. Knowing desktop-first helps you read older code and maintain older sites, and it helps you recognise when a stylesheet is fighting itself with overrides. But your own new work will usually be cleaner, shorter, and more phone-friendly if it begins with the smallest screen.

There is a second, subtler cost to desktop-first: it encourages thinking of the phone layout as a problem to solve after the real design is finished, rather than as a design in its own right. That attitude shows in small decisions — a menu that is merely hidden, a sidebar that is merely stacked, a feature that is merely removed — and visitors notice the difference between a layout designed for their device and one adapted reluctantly. Starting small reverses that attitude and treats the phone as a first-class design target.

Check: What is the main drawback of building desktop-first for a new site?

Section 14 — min-width versus max-width

min-width and max-width are the two most used media features, and confusing them is one of the most common responsive errors. The words themselves give the rule, if you read them carefully. min-width sets a minimum: the condition is true when the viewport is at least that wide. max-width sets a maximum: the condition is true when the viewport is at most that wide. One looks upwards from a threshold, the other looks downwards, and they produce opposite behaviours.

Take @media (min-width: 700px). A viewport 500 pixels wide fails the test, because 500 is less than the minimum of 700. A viewport 800 pixels wide passes, because 800 is at least 700. A viewport exactly 700 pixels wide also passes, because "at least" includes the threshold itself. So min-width queries apply to large screens and accumulate as the screen grows: a 1200-pixel screen matches the 700-pixel query, the 1000-pixel query, and any other min-width query below 1200. That accumulation is what makes mobile-first work: each larger query adds to, rather than replaces, the smaller ones.

Now take @media (max-width: 700px). A 500-pixel viewport passes, because 500 is at most 700. An 800-pixel viewport fails, because it exceeds the maximum. A 1200-pixel viewport fails every max-width query below 1200. So max-width queries apply to small screens and accumulate as the screen shrinks, which is what makes desktop-first work: each smaller query adds an adjustment for an ever-narrower situation.

You can use both in one stylesheet, and sometimes a range is genuinely useful: @media (min-width: 600px) and (max-width: 900px) targets only the middle band, for a tablet layout that should not apply to phones or desktops. Ranges are fine in moderation. What causes confusion is mixing approaches without a plan — some components mobile-first, others desktop-first, with overlapping queries that override each other in hard-to-predict order. The cascade resolves those conflicts by specificity and source order, but a human reading the file will struggle to predict the result.

The practical advice is simple: pick one approach for a project, usually mobile-first with min-width, and use it consistently. If you need a range, write it deliberately and comment its purpose. And whenever a query seems to have no effect, check first whether you wrote min when you meant max — that single word is the cause more often than any other error.

A useful memory aid is to think of min as a floor and max as a ceiling. A min-width query is a floor you must stand on or above; a max-width query is a ceiling you must stay under. When you are debugging, say the floor or ceiling aloud and compare it with the actual viewport width in developer tools. If the viewport is below the floor, a min-width rule cannot apply, and if it is above the ceiling, a max-width rule cannot apply. That check resolves most mysterious non-applying queries.

Check: Does min-width: 700px apply to a 500-pixel screen or an 800-pixel screen?

Section 15 — A two-breakpoint example

A short, complete example ties together everything so far. Imagine a page with a row of cards — for instance, short guides on a learning site. On a phone, the cards should stack in one column so each has room to breathe. On a medium screen, two columns look good. On a wide screen, three columns make better use of the space. Mobile-first CSS expresses that in three steps, and each step changes only one property:

.cards {
  display: grid;
  grid-template-columns: 1fr;
}
@media (min-width: 600px) {
  .cards { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1000px) {
  .cards { grid-template-columns: 1fr 1fr 1fr; }
}

Notice what is not repeated. The base rule sets the grid display and a single flexible column. The first query does not restate display: grid; it only changes the column definition. The second query does the same. Because of the cascade, the display property carries through, and each query builds on the last. This economy is a hallmark of well-written responsive CSS: change only what changes, and let everything else stand.

Also notice the behaviour between breakpoints. At 599 pixels, the layout is one column. At 600 pixels, it becomes two — the threshold is inclusive, so exactly 600 matches min-width: 600px. At 999 pixels it is still two columns, and at 1000 it becomes three. A visitor resizing their window sees clean transitions at those two widths and a stable layout everywhere else. There is no in-between state where the cards are half-arranged, because the column count only changes at the queries.

You can extend this pattern in obvious ways. Add a gap between cards with gap: 1rem in the base rule, and it applies at all sizes. Add padding to the cards once, and it carries through. If the cards need different content order at a size, that is a larger change and belongs in its own thoughtful query, not in a quick tweak to this one. Keeping each query focused makes the stylesheet easy to adjust later: if two columns feel cramped at 600, you change one number to 650 and the whole pattern follows.

Test this example yourself by building a page with six simple cards and resizing the browser. Watch the columns change at 600 and 1000, and notice how little code produced that behaviour. That ratio — a few lines, a large effect — is why the grid-plus-media-query pattern is a staple of modern front-end work.

This example also shows why grid is a good partner for media queries. Changing one property, the column definition, rearranges the whole collection, because the grid handles placement, sizing, and gaps from that single definition. With older float or inline-block layouts, the same change required adjusting widths, margins, and clearing behaviour on every item. Grid concentrates the layout logic in the container, so the media query stays short and the intent stays obvious to anyone reading it later.

Check: At 800 pixels wide, how many columns does that example show?

Section 16 — Responsive images: the width rule

Images are the most common cause of broken responsive layouts, and one short rule prevents most of the damage. It is worth adding to every project before anything else goes wrong:

img {
  max-width: 100%;
  height: auto;
}

The first declaration, max-width: 100%, says an image may never be wider than its containing element. If the container is 800 pixels wide and the image file is 1200 pixels wide, the image displays at 800. If the container narrows to 360 pixels on a phone, the image narrows with it. The image is capped by its container at every size, so it can never push the page sideways. Without this rule, a large image keeps its natural width regardless of the screen, and a phone page overflows.

The second declaration, height: auto, is just as important, though it is easier to overlook. When the width changes, the height must change in proportion, or the image will squash or stretch. height: auto tells the browser to calculate the height from the image's natural proportions once the width is known. An image that is naturally twice as wide as it is tall stays twice as wide as it is tall at every displayed size. If you set both width and height to fixed values, you break that relationship and distort the picture.

There is a subtlety worth knowing. max-width only caps the size; it never enlarges an image beyond its natural size. A small 300-pixel image inside an 800-pixel container will display at 300 pixels, not stretch to 800 and become blurry. That is usually what you want: images should not be upscaled beyond their quality. If you do want an image to fill its container even when small, width: 100% instead of max-width: 100% will stretch it, but at the cost of softness. For photographs, the cap is the safer default.

This rule also interacts well with the aspect-ratio property you will meet later, and with modern image formats and srcset sizes. Those techniques choose which file to download or which shape to preserve, but this rule governs the displayed size in the layout. Apply it globally, early, and you will rarely see the classic symptom of a desktop-sized photograph bursting out of a phone page. It is a small rule with a large return, and experienced developers treat its absence as a bug.

There is one more place this rule helps: images inside flex and grid items. A flex item can shrink below its content size in some situations, but an image with max-width: 100% will shrink with its item rather than forcing the item wider. That behaviour prevents a common grid overflow where a large image stretches its column beyond the intended track size. Combined with a sensible minimum track size, the rule keeps flexible layouts genuinely flexible, even when their content is a large photograph.

Check: What does height: auto protect when an image is resized?

Section 17 — Serving different image sizes with srcset

The width rule in the previous section controls how large an image appears, but it does not control how large a file the visitor downloads. A phone displaying a photograph at 360 pixels wide does not need a 2400-pixel file meant for a large monitor; downloading it wastes data, battery, and time, especially on a slow mobile connection. The srcset attribute solves that by letting the browser choose an appropriately sized file from a list you provide.

A typical example looks like this:

<img src="photo-small.jpg"
     srcset="photo-small.jpg 600w, photo-large.jpg 1200w"
     alt="A market street">

The src attribute still provides a fallback file for browsers that do not understand srcset. The srcset list gives each file a width descriptor: 600w means the file is 600 pixels wide, 1200w means 1200 pixels wide. The browser then considers the displayed size of the image, the screen's pixel density, and the connection, and picks the file that will look good without being wastefully large. On a phone it will usually pick the small file; on a high-density desktop monitor it may pick the large one. You provide the options; the browser makes the judgement, because only the browser knows the exact screen and conditions.

Creating the different sizes is part of the job. An image editor or a build tool can export the same photograph at several widths — for example, 600, 1200, and 1800 pixels — and you list them all in srcset. The effort is modest for a few key images, such as hero photographs, and it pays off on every visit. For small decorative icons, the saving is negligible and a single file is fine; judgement about where to apply srcset is part of the craft.

Note what srcset does not do: it does not change the picture's composition. The small and large files show the same scene, just at different resolutions. If the wide desktop photograph becomes meaningless when shrunk — a distant landscape where the subject vanishes — then you need art direction, a different crop for small screens, which is the subject of the next section. Use srcset when the picture is the same at every size, and use <picture> when the picture itself should change.

To choose srcset sizes well, think about the widths at which the image actually displays, not about abstract device categories. If a photograph displays at roughly 360 pixels on a phone, 700 on a tablet, and 1100 on a desktop, then files near those widths, plus a larger option for high-density screens, cover the real cases. Exporting ten sizes adds maintenance for little benefit, while exporting only one huge file wastes every phone visitor's data. A handful of well-chosen sizes, matched to your layout, is the practical middle path.

Check: Who chooses which file from srcset — you, or the browser?

Section 18 — Art direction with the picture element

Sometimes changing an image's size is not enough, because the image's composition fails at a small size. Consider a wide banner photograph of a market street: on a desktop it shows stalls, people, and buildings in a rich scene. Shrunk to a phone width, the same scene becomes a thin strip in which no detail is recognisable. The photograph is technically responsive — it fits — but it no longer communicates. That is a failure of art direction, not of sizing, and the <picture> element is the tool for it.

The <picture> element lets you offer different images for different conditions, with the browser picking the first one whose condition matches:

<picture>
  <source media="(max-width: 600px)" srcset="photo-portrait.jpg">
  <img src="photo-wide.jpg" alt="A market street">
</picture>

Here, a phone-width visitor gets a portrait crop that focuses on a single stallholder, filling the narrow screen with a meaningful subject. A wider visitor gets the full wide scene. Both images describe the same place, but each is composed for its screen. The final <img> element is required: it provides the fallback and carries the alt text, which applies to whichever source is chosen.

Art direction also serves format choices. A <source> can offer a modern format, such as WebP or AVIF, to browsers that support it, with the <img> fallback in a widely supported format for older browsers. That is a performance and quality improvement with the same mechanism: try the better option first, fall back gracefully. The order of sources matters — the browser uses the first matching source — so list the most specific condition first.

Creating art-directed crops takes editorial judgement, not just exporting. You must look at the small-screen crop and ask whether it still tells the story, whether the subject is clear, and whether the mood survives. A lazy centre crop can cut off a person's face or the key detail. A thoughtful crop, chosen by a human looking at the result, is what makes the technique worthwhile. For that reason, art direction is best reserved for important images — heroes, feature photographs, illustrations that carry meaning — rather than applied mechanically to every picture on a page.

Used well, <picture> completes the responsive image story: max-width controls display size, srcset controls file size, and <picture> controls composition. Together they ensure an image is the right size, the right weight, and the right picture at every screen.

Format art direction deserves a brief mention too, because it uses the same picture element for a different purpose. A source element can test whether the browser supports a modern image format and offer that format first, falling back to a traditional format in the img element. The visitor gets a smaller, better-quality file when their browser supports it, and an ordinary file otherwise, with no visible difference in your markup's structure. It is an easy performance win for hero images, provided you still export the fallback.

Check: When is <picture> a better choice than srcset alone?

Section 19 — Responsive typography with clamp

Headings present a particular responsive problem. A heading that looks confident on a desktop — large, bold, commanding — can become absurd on a phone, wrapping over many lines and pushing the content far down the page. The same heading, sized modestly for a phone, can look timid and lost on a wide monitor. Fixed sizes force you to choose one, and media queries let you choose a few, but the clamp() function lets the size glide smoothly between limits.

The syntax packs three values into one declaration:

h1 {
  font-size: clamp(1.75rem, 5vw, 3.5rem);
}

The first value is the minimum: the heading will never be smaller than 1.75rem, whatever the screen. The third value is the maximum: it will never exceed 3.5rem, however wide the monitor. The middle value is the preferred size, here 5vw, meaning 5% of the viewport width, which grows and shrinks with the window. The browser uses the preferred size whenever it falls between the minimum and maximum, and clamps it to the nearest limit when it would go beyond. The result is type that feels alive — growing with the screen — but never out of control.

A concrete walk-through helps. On a 360-pixel phone, 5vw is 18 pixels, which is below the 1.75rem minimum (about 28 pixels at the default root size), so the heading renders at the minimum: readable, not tiny. On a 1000-pixel tablet or laptop, 5vw is 50 pixels, which sits between the limits, so the heading renders at 50 pixels: generously sized for the space. On a 1600-pixel monitor, 5vw would be 80 pixels, above the 3.5rem maximum (about 56 pixels), so the heading stops at the maximum: prominent, but not overwhelming. One line has replaced what might otherwise have been three media queries.

Choosing good clamp values is a matter of testing the extremes. Pick the minimum by looking at the smallest screen you support and asking whether the heading is readable and well-proportioned there. Pick the maximum by looking at the largest screen and asking whether the heading still relates sensibly to the body text. Pick the preferred value by checking the middle sizes: it should produce a smooth progression, not a jump. Body text, by contrast, usually does not need clamp(); a steady rem size with comfortable line height is more readable for long passages than text that constantly changes size.

Choosing the preferred value in clamp() also benefits from a simple check: look at the size it produces on a typical laptop, where most desktop visitors will see the heading. If that middle size feels right, and the minimum and maximum protect the extremes, the whole range will usually feel right. If the middle size feels too large or too small, adjust the viewport percentage rather than the limits, because the limits are guards, not the main sizing decision. That separation keeps tuning calm and predictable.

Check: What are the three values inside clamp() for?

Section 20 — Fluid type without losing control

Fluid type is type whose size changes continuously with the viewport, rather than jumping between fixed sizes at breakpoints. It can produce beautiful, harmonious pages where headings always feel proportioned to the screen. It can also produce unreadable pages, if it is applied without limits. The difference between those two outcomes is control: fluid type needs a floor and a ceiling, and clamp() is the tool that provides them.

The risk of unlimited fluid type is easiest to see at the extremes, which are exactly the screens beginners forget to test. A heading sized purely in viewport units, such as font-size: 6vw, is 21 pixels on a 360-pixel phone — small for a main heading, though perhaps tolerable — and 115 pixels on a 1920-pixel monitor, where it dominates the page and wraps awkwardly. Worse, if the visitor has set a larger default font size for accessibility, viewport units ignore that preference entirely, because they are tied to the window, not to the visitor's settings. Unlimited fluid type therefore fails both very small and very large screens, and fails readers who need larger text.

clamp() fixes the extremes by construction. The minimum guarantees legibility on the smallest screen and respects a sensible lower bound even if the viewport shrinks further. The maximum guarantees that the heading does not grow into a poster on a television or a wide monitor. Between those bounds, the preferred viewport value gives the smooth scaling that makes fluid type attractive in the first place. You get the benefit — type that breathes with the screen — without the failure modes.

There are still judgements to make. Fluid type works best for display type: main headings, hero text, and short titles where size is part of the visual impact. For body text, long paragraphs, captions, and user-interface labels, a stable rem size is usually better, because constant resizing while a window is dragged is distracting during reading, and because line length and line height are easier to control at a fixed size. A good rule is to let headings flex and body text stay steady.

Test fluid type the way you test breakpoints: at the smallest width, at the largest width, and at several points in between, and with the browser's default font size increased. If the heading is readable and proportioned at every point, and if increasing the default font size still enlarges the text sensibly, the fluid type is under control. If any extreme fails, adjust the minimum or maximum — not the preferred value alone — until it passes.

One more caution applies to fluid type in user interfaces: text that changes size while a window is being resized can cause layout shifts, as buttons and menus reflow around the changing text. For headings on a content page that shift is harmless, but for a navigation bar or a form label it can be distracting or even cause a mis-click as a target moves. That is another reason to reserve fluid sizing for display headings and keep interface text stable, so interactive elements stay where the visitor expects them.

Check: Why does fluid type need a minimum and a maximum?

Section 21 — Flexbox that wraps

Flexbox lays items out along a row or a column, and by default it tries to keep them on a single line, shrinking them if necessary to fit. That default is useful for a toolbar, but it becomes a problem for a row of cards or tags on a narrow screen: the items are squeezed until their content is unreadable, or they overflow the container. The fix is one declaration on the container: flex-wrap: wrap;. With wrapping enabled, items that cannot fit drop onto a new line instead of being crushed.

A typical pattern pairs wrapping with a base size for the items. For example, a container with display: flex; flex-wrap: wrap; gap: 1rem; and items with flex: 1 1 220px; produces a row that fills the available width, with each item at least 220 pixels wide, growing to share extra space, and wrapping when another 220-pixel item would not fit. On a wide screen you might see four items in a row; on a tablet, three; on a phone, one or two. No media query was needed, because the wrapping itself responds to the width. This is sometimes called intrinsic responsiveness: the layout adapts from its own rules, not from an external breakpoint.

Wrapping has details worth learning. The gap property sets consistent spacing between items, both horizontally and vertically, which is far cleaner than using margins on items and then removing the margin from the last item in each row — a fiddly task when the number of items per row keeps changing. The flex shorthand on the items controls how they grow and shrink: the first number is the growth factor, the second is the shrink factor, and the third is the base size before growing or shrinking. A base size that is too large will produce only one column on most phones, which may be what you want for cards, but too small a base will produce cramped columns. Test with real content, not with empty boxes, because a card with a long title behaves differently from an empty rectangle.

Wrapping is not a cure for every layout. When a design needs a precise number of columns, or a specific rearrangement at a size — a sidebar moving, a navigation collapsing — a media query or a grid is the clearer tool. Wrapping excels at collections of similar items: cards, tags, buttons, gallery tiles, and feature lists. For those, it is often the simplest responsive solution, and it keeps working at widths you never explicitly considered, including split-screen windows and unusual devices.

Wrapping also works well with the gap property, which deserves emphasis because older techniques used margins that had to be cancelled on the last item of each row. With wrapping, the last item of a row changes as the width changes, so margin-based spacing required fragile workarounds. Gap avoids all of that: the browser inserts the same spacing between every pair of items, on every row, at every width, and no item needs special treatment. It is a small property that removes a whole category of fiddly CSS.

Check: What happens to flex items when their container runs out of room and wrapping is on?

Section 22 — Changing flex direction at a breakpoint

Wrapping handles collections well, but some layouts need a structural change: a column on a phone that becomes a row on a desktop. The classic example is a page with a main article and a sidebar. On a phone, the sensible arrangement is stacked: article first, sidebar below, each using the full width. On a desktop, the sensible arrangement is side by side: article taking most of the width, sidebar beside it. Flexbox expresses that change with a single property switched inside a media query:

.layout {
  display: flex;
  flex-direction: column;
}
@media (min-width: 700px) {
  .layout { flex-direction: row; }
}

The base rule sets the direction to column, stacking the children vertically. The query, which applies at 700 pixels and wider, changes the direction to row, placing the children horizontally. Everything else — the display, the gap, the padding — carries through unchanged, because only the direction needed to change. That economy is the same principle you saw with the grid example: change one property at the breakpoint, not the whole component.

Once the direction is a row, you usually need to say how the children share the width. A common approach gives the main content a larger flex value than the sidebar, for example .main { flex: 3; } .sidebar { flex: 1; }, so the main area takes three quarters of the space and the sidebar one quarter. On the phone, where the direction is a column, those flex values affect height rather than width, which is usually harmless, but it is worth checking: a sidebar with a large flex value in a column layout could stretch unexpectedly. If that happens, set the widths or flex values inside the media query as well, so each direction has its own sizing rules.

Order deserves a thought here too. In the stacked phone layout, the HTML order decides what appears first, and that is usually the main content, which is what phone visitors and screen reader users meet first. When the direction becomes a row, the same HTML order places the main content on the left and the sidebar on the right in left-to-right languages. That is normally correct. Resist the temptation to reorder visually with the order property unless you have a strong reason, because visual order that differs from HTML order can confuse keyboard and screen reader users, who follow the HTML order.

A detail that often surprises developers is that flex-direction also affects the main and cross axes, so properties like justify-content and align-items swap their visual meaning when the direction changes. In a row, justify-content distributes items horizontally; in a column, it distributes them vertically. If your spacing looks wrong after switching direction, check those alignment properties before assuming the direction itself is at fault. Naming the axes in a comment can help a future reader follow the same reasoning.

Check: At what width does that example switch from a column to a row?

Section 23 — Responsive grids with auto-fit and minmax

CSS Grid can produce a responsive layout without a single media query, using a pattern that looks cryptic at first but becomes intuitive once its parts are understood:

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
}

Read it piece by piece. repeat() repeats a column definition as many times as needed. auto-fit tells the browser to fit as many columns as will fit in the container. minmax(220px, 1fr) defines each column: it must be at least 220 pixels wide, and it may grow to one fraction (1fr) of the available space, sharing equally with its neighbours. Put together, the browser works out how many 220-pixel columns fit, creates that many, and stretches them equally to fill the row. Narrow the window, and a column drops away when it no longer fits; widen it, and a column returns.

The minimum in minmax() is the key design decision. It should be the narrowest width at which a card still looks and reads well. For a card with an image, a title, and a short paragraph, 220 pixels might be right; for a card with a wide table or a long word, it might need to be larger. If the minimum is too small, cards become cramped columns of a few words per line. If it is too large, the grid collapses to a single column sooner than necessary, wasting space on tablets. Test with your real content, including the longest title and the longest word, because those are what set the true minimum.

auto-fit and auto-fill are easily confused, and the difference matters when there are fewer items than columns. auto-fit collapses empty columns, so the existing items stretch to fill the row. auto-fill keeps empty columns in place, so items stay at their minimum size and empty space remains at the end of the row. For most galleries and card lists, auto-fit gives the fuller, more intentional look. For a layout where items should keep a fixed size regardless of how many there are, auto-fill may be preferable. Try both with three items in a wide container and the difference becomes immediately visible.

This pattern does not replace media queries entirely. It handles "how many columns fit," but not "change the whole structure" or "show a different navigation." It is, however, a powerful default for collections, and it responds smoothly to every width, including ones you never listed as breakpoints. That smoothness is its strength: there is no jump, only a gradual dropping and adding of columns.

Another useful grid detail is that minmax() can use a percentage or an automatic minimum as well as a fixed pixel value, but a pixel minimum is the clearest for cards, because it directly states the narrowest usable card. If your cards contain images, remember that the image's own minimum size can force a column wider than you intended, so pair the grid rule with the responsive image rule from earlier. Together they ensure the column minimum, not the image file, controls the layout.

Check: In that grid rule, what does minmax(220px, 1fr) guarantee?

Section 24 — Collapsing a grid at a breakpoint

Auto-fitting grids handle column counts beautifully, but some layouts need more than a different number of columns — they need a different structure. A dashboard, for example, might show four panels in a two-by-two grid on a desktop, with a chart spanning two columns, while on a phone it should become a single column with the most important panel first. That is a job for a media query, because the change is structural and deliberate, not merely a matter of fitting.

In such a case, the base styles describe the phone structure: a single column, panels in priority order. A media query at a larger width then redefines the grid: perhaps grid-template-columns: 1fr 1fr; with a named area or a span for the chart. Because grid placement is declared in the stylesheet, the change is explicit and readable: anyone opening the file can see that the desktop layout is a two-column arrangement and the phone layout is a stack. That explicitness is an advantage over trying to coax the same result from auto-fitting alone.

A word of caution about reordering. Grid lets you place items visually in any order, regardless of their HTML order, using placement properties. That power can create a mismatch between what sighted users see and what keyboard users and screen readers encounter, because those users follow the HTML order. If a panel appears first visually but third in the HTML, a screen reader user will meet it third, and a keyboard user tabbing through will jump around the screen in a confusing way. The safer approach is to put the most important content first in the HTML, so the stacked phone layout and the visual desktop layout agree on priority. Use visual reordering only for decoration or for cases where the orders genuinely coincide.

Another practical point is to keep the collapsed layout genuinely usable, not merely narrower. A dashboard panel designed for a wide grid may contain a chart that becomes illegible when squeezed into a phone column, or a table that overflows. Collapsing the grid is the moment to check each panel's content at phone width: does the chart still read, does the table scroll within its panel, does the heading fit? If a panel's content cannot survive the collapse, the panel itself needs a responsive redesign, not just a new grid position.

When a grid collapses, also consider whether any panel's internal layout needs to change, not just its position. A panel that showed a chart beside a legend on a desktop may need the legend below the chart on a phone, and a panel with two small statistics side by side may need them stacked. Those internal changes are themselves small responsive adjustments, best made in the same media query as the grid collapse, so the panel and its container change together and are tested together.

Check: Why is changing the HTML order often better than reordering with CSS alone?

Section 25 — Hiding content on small screens: handle with care

Hiding content at a given screen size is easy in CSS: inside a media query, set display: none; on the element, and it vanishes from the layout at that size. The technique is legitimate for decoration — a large background illustration, a secondary graphic, or a repeated logo that adds nothing on a phone. It becomes a problem when it is used to hide real content or functionality from phone visitors, because those visitors may need exactly what was hidden.

The risk is easy to underestimate. A designer working on a desktop may look at a crowded page and decide the phone version should hide the sidebar, the related articles, and the detailed specifications to "keep it clean." But a phone visitor is not a lesser visitor: they may be researching a purchase, checking a detail, or trying to complete a task, and the hidden detail may be the one they came for. If the only way to reach an action or a piece of information is through content that is hidden on their device, the site has failed them, even though it looks tidy.

Before hiding something, work through gentler alternatives. Can the content be shortened rather than removed — a long paragraph reduced to a summary with a link to the full text? Can it be stacked below the main content instead of beside it, so it remains available by scrolling? Can it be moved into a disclosure, such as a details element or an expandable section, that the visitor can open if they want it? Each of these keeps the content reachable while still respecting the small screen. Hiding should be the last resort, not the first instinct.

There are also technical consequences. display: none removes the element from the accessibility tree as well as from the visual layout, so screen reader users on any device will not encounter it while it is hidden — which is correct for decoration, but means hidden interactive controls are unreachable by keyboard too. If you hide a navigation menu with display: none and reveal it only on hover, touch and keyboard users may never reach it. Any hidden-and-revealed pattern must be operable by keyboard and announced properly, which is a subject Chapter 14 returns to.

A good rule to carry forward: hide decoration freely, hide content reluctantly, and never hide the only route to an important action. When you do hide something, leave a comment in the CSS explaining why, so a future maintainer does not have to guess whether the content was unimportant or merely inconvenient.

Hiding also has a search and sharing consequence worth noting: content hidden with display: none at all sizes, or hidden on the only device a visitor uses, may as well not exist for that visitor, even if it exists in the HTML. That is fine for decoration, but for product details, prices, opening hours, or contact information, invisibility is a real loss. If the information matters to a task, it should be reachable on every device, even if its presentation changes, because visitors judge a site by what they can actually use.

Check: When is hiding content with display: none a bad idea?

Section 26 — Responsive navigation patterns

Navigation is where responsive design is most visible, because a horizontal menu that fits comfortably on a desktop will overflow a phone almost immediately. A site with six or seven top-level links, each a reasonable width on a desktop, becomes an unusable wrapped mess or a sideways-scrolling strip on a phone. Every responsive site therefore needs a navigation pattern for small screens, and choosing it well matters more than most layout decisions.

The most common pattern is the menu button, often shown as three horizontal lines and called a hamburger menu. On small screens, the navigation links are hidden and a button is shown; tapping the button reveals the links, usually as a vertical list. On larger screens, a media query hides the button and shows the full horizontal row. The pattern works because it preserves all the links while using almost no space when closed. Its weakness is discoverability: visitors must tap to see what sections exist, so it suits sites where visitors usually arrive at a specific page rather than browsing by menu.

Other patterns suit other sites. A priority pattern shows as many links as fit and tucks the rest behind a "More" button. A bottom navigation bar, common in apps, places a few key destinations within thumb reach at the foot of a phone screen. A simple vertical list, always visible, suits a small site with few links and avoids hiding anything. The right choice depends on how many links there are, how important browsing is, and what your visitors actually do — which you can learn from usage data or simply from thinking honestly about the site's purpose.

Whatever pattern you choose, three requirements are non-negotiable. First, the menu must be reachable by keyboard: a visitor tabbing through the page must be able to open it, move through its links, and close it, without getting trapped. Second, it must be usable with a screen reader: the button needs a clear label, and its expanded or collapsed state should be announced. Third, the links must remain real links, not text that only works with a mouse click handler. A menu that only a mouse can operate, or that hides its links from assistive technology, is broken however elegant it looks.

Test navigation on a real phone with your thumb, on a desktop with only the keyboard, and with the browser window at widths just above and below your breakpoint. Navigation is the gateway to everything else on the site; if it fails at a size, the whole site fails at that size.

A final navigation detail is the behaviour when a menu is open and the visitor resizes the window or rotates the phone. A menu that was open in a small layout should not remain as a stray overlay when the layout switches to the full horizontal row, and a menu button that was hidden on a desktop should reappear cleanly when the window narrows again. Testing that transition — opening the menu, then resizing across the breakpoint in both directions — catches state bugs that static screenshots never show.

Check: What must stay true of a mobile menu for keyboard users?

Section 27 — Responsive tables

Tables are among the hardest elements to make responsive, because their columns have a minimum sensible width that cannot be compressed indefinitely. A table of product specifications, with columns for name, price, weight, and stock, may read perfectly on a desktop, but on a phone those four columns squeezed into 360 pixels become unreadable, or the table forces the page sideways. The challenge is to preserve the table's meaning — rows and columns and their relationships — while fitting a narrow screen.

The most practical default is to let the table scroll sideways inside its own container, rather than letting the whole page scroll. Wrap the table in a div and give that div overflow-x: auto;. On a wide screen the table displays normally and no scrolling is needed. On a narrow screen the table keeps its natural width, and the visitor scrolls just the table left and right within its box, while the rest of the page — headings, navigation, surrounding text — stays put. That containment is the key benefit: sideways movement is confined to the table, so the page as a whole remains stable and readable.

Scrolling tables have a usability cost worth acknowledging: a visitor may not realise the table scrolls, especially if no scrollbar is visible on a touch device. Mitigations include keeping the table's first column — usually the name or identifier — visible where possible, using a subtle visual hint such as a faded edge, and avoiding tables with so many columns that scrolling becomes a chore. If a table has ten columns, it may be worth asking whether all of them belong in one table, or whether the data should be split, summarised, or presented differently on small screens.

An alternative for simple tables is to restack each row into a card: on a phone, each row becomes a block with labelled fields, such as "Name: Widget, Price: £12." This can read beautifully, but it is more work to build and maintain, and it risks breaking the table semantics that screen readers rely on. If you restack, you must preserve the association between each value and its heading, for example by repeating the heading as a label in the card. For complex or data-heavy tables, the scrolling container is the safer, more honest default, and restacking is best reserved for simple cases where you can verify the result with a screen reader.

For accessibility, a scrolling table container should keep its header row associated with its data, which ordinary table markup already does, and keyboard users should be able to reach and scroll the container. A container that only scrolls by touch, with no keyboard path, excludes keyboard visitors from the data. Making the container focusable and ensuring its scroll position can be changed with arrow keys, or simply ensuring the table itself remains navigable, preserves access to the information the table exists to convey.

Check: Why wrap a wide table in a scrolling container instead of letting the whole page scroll sideways?

Section 28 — Responsive forms

Forms are where responsiveness meets real user effort, because a form is not just read — it is filled in, often on a phone keyboard, possibly in a hurry. A form layout that works on a desktop, with labels beside inputs in neat rows, can become cramped and error-prone on a phone if it is not adapted. The core responsive principle for forms is simple: stack on small screens, sit side by side only when there is room.

Stacking means each label sits directly above its input, and the input uses the full available width. That arrangement has several benefits on a phone. The label is always visible while typing, because it is not squeezed into a narrow column beside the field. The input is wide enough to see what has been typed, which reduces errors, especially for email addresses and passwords. And the tap target is large: the whole width of the screen is available to tap into the field. A half-width input on a phone, by contrast, is fiddly to tap and shows only a few characters at a time, so the visitor cannot easily check their entry.

At larger widths, a side-by-side layout can be appropriate, particularly for short fields such as a name and a postcode on one row, or a label column beside a set of inputs. A media query can switch the form row to a horizontal flex layout at, say, 700 pixels, while keeping the stacked layout below that. Even then, keep labels associated with their inputs in the HTML — a visual arrangement must never break the label-input connection that screen readers and tap targets rely on. Chapter 14 covers that association in detail.

Other form details also respond to screen size. On a phone, use the appropriate input types — email, tel, number — so the device shows the right keyboard, which is a responsiveness of input, not just layout. Keep help text close to its field, and make sure error messages appear where the visitor is looking, not at the top of a long form they have scrolled past. Avoid splitting a single piece of information, such as a phone number, across multiple small inputs on a phone, because moving between tiny fields on a touch keyboard is frustrating. And always test a form by actually completing it on a phone, with your thumb, because a form that looks fine in a desktop preview can still be miserable to use.

A further form consideration is the order of fields on a small screen. A form that asks for a long, rarely needed detail before the essential information forces phone visitors to scroll and type before they reach the point of the form. Reordering fields so the essential ones come first, with optional detail later or grouped under a clearly labelled section, respects the visitor's time and reduces abandonment. That ordering is a content decision, but it is most visible — and most painful when wrong — on a small screen.

Check: Where should a form label sit on a small screen, and why?

Section 29 — Touch targets on small screens

A mouse pointer is precise: it can click a link only a few pixels tall without difficulty. A finger is not precise. It is wider, it covers what it touches, and it cannot hover to preview a target before committing. Those physical facts mean that controls designed for a mouse often fail on a touch screen, even when the layout around them is perfectly responsive. Touch target size is therefore a responsive concern in its own right.

The practical rule is generosity: give buttons and links comfortable padding, and space neighbouring targets apart so a tap on one does not accidentally hit another. A row of small text links packed tightly together may look elegant on a desktop, but on a phone a thumb aiming for one link will regularly land on its neighbour. Increasing the padding enlarges the tap area without enlarging the text itself, which is an efficient fix: the visual design stays refined, while the interactive area grows. Similarly, adding vertical space between list items or menu entries reduces mis-taps far more than it harms the design.

Placement matters as well as size. Controls near the bottom of a phone screen are within easy thumb reach; controls at the very top may require stretching or a second hand. Primary actions — the button a visitor most needs — should be easy to reach and hard to miss, not tucked into a corner. Destructive actions, such as deleting something, deserve the opposite treatment: enough separation and, ideally, a confirmation step, so a mis-tap cannot cause harm. These are design judgements, but they start from the same observation: a thumb is not a mouse.

Testing is straightforward and should be physical. Open your page on a phone, hold it as you normally would, and try to complete the key tasks with your thumb alone: navigate, fill a field, submit a form, follow a link. Note every target you miss, every link you hit by accident, and every button that feels too small. Then fix those targets with padding and spacing, and test again. No simulator reproduces the feel of a thumb on glass, and a page that passes a desktop click test can still fail a thumb test. When in doubt, make the target bigger: visitors rarely complain that a button was too easy to tap.

Spacing between targets also interacts with scrolling: a list of links with generous spacing is easier to tap accurately while scrolling, because the finger's landing point is less likely to coincide with a neighbouring link as the list moves. Dense lists, by contrast, turn scrolling into a hazard, where lifting the finger can accidentally activate a link. If visitors report accidental taps, the first fix to try is usually more space between targets, not smaller text or a different layout structure.

Check: Why can a button that works well with a mouse fail on a phone?

Section 30 — The 100vh trap on mobile browsers

Setting a section to height: 100vh; looks like a neat way to make it fill the screen exactly: 100 viewport height units should equal the full height of the window. On a desktop that is usually true. On many mobile browsers it is not, and the difference produces one of the more confusing responsive bugs, because the page looks correct in a desktop preview and wrong on a real phone.

The cause is the mobile browser's own interface. On a phone, the address bar and toolbar appear and disappear as the visitor scrolls, so the visible height of the page changes during use. Some mobile browsers define 100vh using the largest possible viewport — the height when the toolbars are hidden — rather than the currently visible height. A hero section set to 100vh may therefore be taller than the visible area when the toolbars are showing, hiding its bottom content, such as a button, below the fold. As the visitor scrolls and the toolbars hide, the section can appear to jump or resize. The effect is jarring and, worse, it can hide the very action the hero was designed to promote.

Modern CSS provides a more accurate unit: dvh, dynamic viewport height, which tracks the actually visible height as toolbars appear and disappear. A section set to height: 100dvh; follows the visible area rather than the largest possible area. Support for dvh is now broad in modern browsers, but older browsers will ignore a declaration they do not understand, so a sensible pattern is to declare a fallback first and the dynamic value second:

.hero {
  height: 100vh;
  height: 100dvh;
}

A browser that understands dvh uses the second rule; one that does not keeps the first. That progressive approach is a general CSS habit worth learning: offer a safe value, then a better one.

Even with dvh, caution is wise. A full-height hero is a strong design statement, but it pushes all other content below the first screen, and on a short landscape phone it can leave almost no room for text. Consider whether a hero truly needs to fill the screen, or whether a generous but not total height — for example, a minimum height with comfortable padding — would serve the visitor better. And always test full-height sections on a real phone, scrolling up and down, because that is the only way to see the toolbar behaviour that causes the trap.

Another height-related trap is using vh for a fixed header or footer combined with a full-height section, which can double-count the viewport and push content off screen on a phone. A safer pattern gives the hero a minimum height rather than an exact height, so it can grow if its content needs more room, and lets the header sit in normal flow or as a modest overlay. Minimum heights bend where exact heights break, and they are generally the more forgiving choice for content whose length you cannot fully predict.

Check: Why can height: 100vh behave unexpectedly on a phone?

Section 31 — Orientation and other media features

Width is the workhorse of responsive design, but media queries can test other features of the viewing environment, and knowing them lets you refine a layout in ways width alone cannot. Two of the most useful are orientation and pointer characteristics, and each answers a different question about the visitor's situation.

Orientation asks whether the viewport is taller than it is wide, or wider than it is tall. (orientation: portrait) is true for a phone held upright; (orientation: landscape) is true for the same phone turned sideways, or for a typical laptop screen. This matters because a layout that works in portrait may fail in landscape, even though the width has grown. A phone turned sideways gains width but loses height, so a tall hero section or a long vertical menu that was fine in portrait can suddenly swallow the whole screen. An orientation query can, for example, reduce a hero's height or switch a menu to a compact row when the device is landscape.

Pointer and hover features ask about input, not shape. (pointer: coarse) suggests a touch screen, where the primary pointer is imprecise; (pointer: fine) suggests a mouse or stylus. (hover: hover) means the device can hover, as a mouse can; (hover: none) means it cannot, as on most touch screens. These are valuable for details: a control that reveals extra information on hover should also reveal it on tap for a (hover: none) device, and a target that is comfortable for a fine pointer may need enlarging for a coarse one. Note the careful wording — these features are hints, not certainties, because a laptop with a touch screen can have both a fine and a coarse pointer. Use them to refine, not to make absolute assumptions.

Other features include resolution, for serving sharper images to high-density screens, and user preferences such as colour scheme and reduced motion, which later chapters cover in their own contexts. The general lesson is to keep width as the main breakpoint tool, because width directly determines how much room a layout has, and to use other features as refinements for specific problems. An orientation query that fixes a landscape hero, or a pointer query that enlarges a touch target, is a targeted improvement. A stylesheet driven entirely by orientation or device guesses, without regard to width, will miss the simple fact that a narrow landscape phone and a wide landscape monitor are very different places to lay out a page.

Media queries can also test for scripting and update frequency in some contexts, but those features are rarely needed for ordinary responsive layout, and overusing exotic features makes a stylesheet harder to understand. A good rule is to reach for width first, orientation or pointer second when a specific problem demands it, and anything else only when you have a concrete reason and have checked support. Restraint keeps the stylesheet readable and the layout predictable across browsers.

Check: Name two media features other than width that a query can test.

Section 32 — Container queries: responding to a parent, not the page

A media query responds to the whole viewport: it asks how wide the browser window is. That is usually the right question, but sometimes it is the wrong one. Imagine a card component used in two places on the same site: once in a wide main content area, and once in a narrow sidebar. The viewport is the same in both cases, so a media query gives both cards the same layout, even though one card has far more room than the other. The card should respond to its own space, not to the page's space. Container queries solve exactly that problem.

A container query works in two steps. First, you mark an element as a container, telling the browser that its size should be observable: for example, .sidebar { container-type: inline-size; }. Second, you write a query against that container's size, such as @container (min-width: 400px) { .card { flex-direction: row; } }. Now the card lays out in a row when its container is at least 400 pixels wide, and stacks when its container is narrower — regardless of the viewport width. The same card component adapts differently in the sidebar and in the main area, because it is listening to its immediate surroundings.

This is a genuinely different mental model from media queries, and it suits component-based design, where the same component is reused in many slots. A product card, a user profile, a news teaser — all of these may appear in a full-width list, a two-column grid, and a sidebar, and container queries let each instance choose the arrangement that fits its slot. Without them, developers resorted to writing separate variants of a component for each slot, or to media queries that only approximately matched the component's actual space.

Container queries are newer than media queries, so support, while now broad in modern browsers, is not universal in very old ones. The safe approach is progressive: build a solid base layout that works everywhere, then enhance it with container queries where supported, so older browsers still get a usable component. You can test support in your target browsers before relying on them for a critical layout, and you can keep media queries for page-level structure — the overall columns, the navigation, the container widths — while using container queries for component-level adaptation inside those structures. The two tools complement each other: media queries shape the page, container queries shape the pieces within it.

Container queries also change how you think about testing a component. Instead of testing it only at page widths, you test it in each slot where it appears: the sidebar, the main column, and the full-width list. A component that looks right in a wide main area may still fail in a narrow sidebar, and that failure will not show up in a viewport test. Adding a quick check of each slot to your testing routine catches those component-level failures before visitors meet them in the one place you forgot to look.

Check: What size does a container query respond to, and how is that different from a media query?

Section 33 — Responsive spacing

Layout is not the only thing that should respond to screen size; spacing should too. Padding, margins, and gaps that feel generous on a desktop can waste precious room on a phone, while spacing that suits a phone can feel cramped and mean on a wide screen. Responsive spacing means letting those values grow in steps with the screen, just as columns do, so the page always feels proportioned to its space.

A simple pattern illustrates the idea. A card might start with modest padding on a phone, where every pixel counts and content must stay close to the edge to remain readable:

.card { padding: 1rem; }
@media (min-width: 700px) {
  .card { padding: 2rem; }
}

On the phone, 1rem of padding frames the content without stealing much width. On the desktop, 2rem gives the same content room to breathe, and the card feels more substantial. The content has not changed; the air around it has. That difference in air is what makes a design feel intentional at both sizes rather than merely shrunken or stretched.

The same principle applies to gaps between items, margins between sections, and line height. A section gap of 2rem might separate articles nicely on a phone, while 4rem suits a desktop's larger canvas. A grid gap that is comfortable at one column count may need enlarging when the columns multiply. These are small adjustments, but they accumulate into the overall feeling of a page: cramped or spacious, rushed or calm.

There is a balance to strike. Spacing that grows too aggressively can push important content far down a desktop page, forcing extra scrolling for no benefit. Spacing that never grows can make a wide page feel like a phone page stretched out, with content huddled in the middle of empty space. The test is visual and tactile: look at the page at phone, tablet, and desktop widths, and ask whether the white space feels deliberate at each one. If a section looks crowded, add room at that size; if it looks lost, the container or the spacing needs attention. Responsive spacing is less about rules and more about that repeated looking, guided by a few well-placed queries.

Responsive spacing also applies to line height and paragraph spacing, which are part of how spacious a page feels. A line height that is comfortable for a narrow phone column can feel tight when the same text stretches wider on a desktop, because longer lines need slightly more leading for the eye to track them. Increasing line height modestly at larger widths, alongside padding and gaps, keeps reading comfortable across sizes, and it is a refinement worth adding once the main layout is settled. Test the result on a real phone as well as in the browser's device preview, because perceived spacing changes with actual screen size and viewing distance.

Check: Why should padding change at a breakpoint rather than staying fixed?

Section 34 — Aspect ratios for responsive media

Many boxes on a page must keep their shape while resizing. A video player should stay widescreen, a photograph card should stay in its intended proportions, and a map embed should not become a tall strip on a phone. In the past, developers preserved shapes with a trick involving percentage padding, which worked but was hard to read and easy to break. The aspect-ratio property replaces that trick with a direct statement of intent:

.video {
  aspect-ratio: 16 / 9;
  width: 100%;
}

Here, the width is fluid — it takes the full width of its container, whatever that is — and the height is calculated automatically to keep a 16:9 ratio. On a 1600-pixel container the box is 900 pixels tall; on a 320-pixel phone it is 180 pixels tall; the shape is identical, only the scale changes. That automatic height is the point: you declare the shape once, and the browser maintains it at every size, without you recalculating anything.

Aspect ratio is useful beyond video. A card image area set to aspect-ratio: 4 / 3 keeps a consistent look across a gallery, even if the source images differ slightly in size, provided they are also set to fill the area sensibly. A square avatar area set to aspect-ratio: 1 / 1 stays square in any layout. And because the ratio is declared on the box itself, the browser can reserve the correct amount of space before the media loads, which reduces the jarring jump that happens when a page reflows as images arrive — a performance and usability benefit as well as a layout one.

There are details to handle. If a box has both an aspect ratio and content that needs more height than the ratio allows — for example, a text caption inside a fixed-ratio card — the content may overflow. In that case, the ratio should apply to the media area only, not to the whole card, with the caption outside it. Also, aspect ratio works best when one dimension is fluid and the other is derived; setting both width and height explicitly will override the ratio. Used in that way — ratio on the media box, fluid width, derived height — it is one of the cleanest responsive tools available, and it removes an entire class of distorted or jumping media.

Aspect ratio also helps with layout stability during loading, which is worth stating plainly: when the browser knows a box's ratio before its image arrives, it can reserve exactly the right amount of space, so surrounding content does not jump down the page when the image finally loads. That jump, known as layout shift, is annoying for readers and can cause mis-clicks when a button moves just as a visitor taps it. Declaring ratios on media boxes is therefore both a design choice and a courtesy to the reader.

Check: If a box is aspect-ratio: 16 / 9 and 320 pixels wide, how tall is it?

Section 35 — Testing by resizing the browser

The fastest and most useful responsive test requires no special tool at all: open your page in a browser and drag the window narrower and wider, watching how the layout behaves. This simple act reveals more than any checklist, because you see the layout strain in real time. Do it often while building, not once at the end, when fixes are more expensive and more entangled with other work.

What you are looking for is strain: the moments where the design stops working. Text may overflow its box, or wrap in an awkward place, or become a single word per line. Cards may squeeze until their images are slivers. Navigation may wrap onto two lines or push a link off the edge. A sidebar may crowd the main content until neither is readable. Each strain point is information: it tells you where a breakpoint belongs, where a flexible technique should replace a fixed one, or where content needs shortening. Write down the approximate width of each strain point as you find it, because those notes become your breakpoints, chosen from evidence rather than from a list.

Resizing also reveals problems that only appear between breakpoints. A layout can look perfect at exactly 700 pixels and exactly 1000 pixels, yet awkward at 850, where a grid has an orphan item or a heading wraps badly. Because you are dragging continuously rather than jumping between preset device sizes, you see those in-between states. That is an advantage over testing only at a few device widths: real visitors use every width, including split-screen windows and resized desktop browsers, not just the widths of popular phones.

Make resizing a habit during development. After adding a component, drag the window through its full range and watch it. After adding a media query, drag across its threshold in both directions and confirm the change is clean. Keep the window at a phone width while you write content, to notice long words or wide elements early. This habit costs seconds each time and saves hours of debugging later, because responsive bugs found early are usually one-line fixes, while responsive bugs found after launch are redesigns.

Resizing also helps you notice performance clues, such as images that look soft when enlarged or text that reflows awkwardly around an image. Those clues often point to a missing srcset size, an image that is too small for its container, or a float that should have become a flex layout. Noting them during resizing, while the component is fresh in your mind, makes the fix a small adjustment rather than a later investigation, and it builds the habit of seeing layout and content as one system.

That habit also builds intuition over time, so you begin to anticipate breaking points before you test them, and your first drafts need fewer corrections.

Check: What should you write down while dragging the browser window narrower?

Section 36 — Device mode in developer tools

Every major browser's developer tools include a device mode — sometimes called responsive design mode — that simulates a phone or tablet screen inside the desktop browser. You can pick a device size, or drag to any custom width and height, and the page re-renders as if it were on that screen. Device mode also simulates touch events, device pixel density, and sometimes network throttling, so you can see how a page behaves on a slower connection. For quick, repeated checks during development, it is invaluable.

To use it well, start from the habit in the previous section: resize freely, but now with device presets as additional checkpoints. Check the common widths, check your own breakpoints, and check the awkward in-between sizes. Use the touch simulation to test menus and buttons with clicks that behave like taps, and use the pixel density setting to see whether images look sharp or blurry on a high-density screen. Use network throttling occasionally to feel how long a page takes on a slow connection, because a layout that is responsive in shape but slow to load is still a poor phone experience.

Device mode has clear limits, and knowing them prevents false confidence. It is a simulation running on a powerful desktop computer, so it cannot reproduce a real phone's processor speed, memory limits, or battery behaviour. It cannot reproduce the feel of a thumb on glass, the way a browser's address bar appears and disappears, or the way a page behaves when the phone is rotated in a hand. It also cannot reproduce the exact rendering quirks of every real device's browser, especially older ones. A page that passes device mode can still fail on a real phone, and a page that looks slightly off in device mode may be fine in reality.

The right relationship is therefore: device mode daily, real device before launch. Use the simulator for the dozens of small checks during building, because it is fast and convenient. Then, before shipping, open the page on at least one real phone, on a real network, and complete the key tasks by hand. The simulator finds most problems; the real device finds the ones that matter most to visitors.

Device mode is also useful for checking pixel density, because an image that looks crisp on a standard desktop monitor may look soft on a phone screen that packs twice as many physical pixels into the same area. Switching device mode to a high-density setting shows that softness before launch, and it prompts the srcset or higher-resolution export that fixes it. That check takes seconds in device mode and saves a real visitor from a blurry hero image on their new phone.

Check: What can device mode not reproduce that a real phone can?

Section 37 — Testing on a real device

Nothing replaces opening your page on an actual phone. Device mode is a useful simulation, but a real device is the environment your visitors actually use, with its real processor, real network, real browser interface, and real human hand. Testing there is not a luxury for large teams; it is a basic step any developer can take with the phone they already own.

A real-device test reveals several things a desktop cannot. Performance is the first: a page that feels instant on a desktop with fast broadband can be sluggish on a phone processor over a mobile network, with images and scripts taking seconds to arrive. That sluggishness changes how the page feels, even if the layout is identical. Browser interface behaviour is the second: the address bar appearing and disappearing, the keyboard covering half the screen when a form field is focused, and the way a full-height section behaves — all of these are real-phone phenomena that a simulator approximates at best. The third is physical usability: whether buttons are reachable with a thumb, whether text is readable in daylight, whether a menu is easy to open one-handed. Those are judgements made with a hand, not with a mouse.

Practical real-device testing does not require a laboratory. Start with your own phone, on both Wi-Fi and mobile data if possible, and try to complete the site's key tasks: find information, follow a link, fill in a form, make a purchase or send a message. Then, if you can, borrow a different phone — a different size, a different browser, an older model — because a page that works on one phone may fail on another, especially an older one with a smaller screen or an outdated browser. Friends, family, and colleagues are usually happy to spend two minutes opening a page and reporting what looks wrong.

Record what you find in the same way as resizing notes: the device, the width, the problem, and a screenshot if possible. Fix the problems, then retest on the same device, because a fix for a desktop layout can easily introduce a new phone problem. That loop — test, fix, retest on a real device — is what turns a page that is responsive in theory into a page that is responsive in a visitor's hand.

Real-device testing also exposes operating system differences that a desktop cannot show, such as how a phone's keyboard behaves when a form field is focused, how its share sheet handles a link, or how its browser renders a particular font. Those details rarely break a page outright, but they shape whether the page feels native to the device or merely tolerated by it. A page that feels at home on a phone, rather than merely fitting on one, is usually a page that was tested on one.

Check: Name two things a real-device test can reveal that a desktop test cannot.

Section 38 — Performance is part of responsiveness

Responsiveness is often discussed as if it were only about layout — columns, breakpoints, and image sizes on screen. But a page that rearranges beautifully on a phone while downloading desktop-sized files onto that phone is not truly responsive. The visitor's experience is shaped as much by how long the page takes to arrive and become usable as by how it looks once it does. Performance, especially on mobile networks and devices, is therefore part of responsiveness, not a separate concern.

The clearest example is images. A hero photograph exported at 2400 pixels wide may be appropriate for a large monitor, but sending that file to a phone that displays it at 360 pixels wastes data and time. On a slow connection, the visitor may wait seconds for an image they will never see at full size, and on a limited data plan, they pay for that waste. The srcset technique from earlier in this chapter exists precisely to avoid this: the phone downloads a smaller file, the desktop downloads a larger one, and each gets what it actually displays. The same logic applies to scripts and styles: code that is only needed for a desktop feature should not be forced onto every phone visitor.

Device capability matters too. A phone processor is less powerful than a desktop processor, and a page with heavy animations, large scripts, or complex layouts will feel slower there even on a fast connection. Animations that are smooth on a desktop can stutter on a phone, and a layout that recalculates constantly can drain battery. Testing on a real device, as the previous section advised, is how you notice this: if a page feels heavy in the hand, it is heavy, whatever the desktop preview suggested.

A responsive performance mindset can be summarised as: send what the device needs, no more. Appropriately sized images, scripts loaded only when their feature is used, styles kept lean, and animations that respect the device's capabilities. None of this requires advanced optimisation; it requires remembering, at each decision, that the phone visitor is not a desktop visitor with a smaller window, but a visitor with a different device, connection, and context. A page that respects that difference is responsive in the fullest sense.

Performance responsiveness also includes respecting a visitor's data setting where the browser exposes it, for example by avoiding autoplay video or very large images when a connection is slow. Even without special APIs, the habits in this chapter — sized images, lean scripts, and modest embeds — already respect slow connections, because they reduce what must be downloaded before the page becomes usable. A page that becomes usable quickly on a slow connection earns trust that a merely pretty page does not.

Check: Why is a phone user hurt more than a desktop user by an oversized image?

Section 39 — Avoid fixed pixel widths on layout boxes

A layout box set to a fixed pixel width is a future overflow bug waiting for a narrower screen. It may look perfect on the screen you are designing for, but sooner or later a visitor will arrive on a screen narrower than that width — a small phone, a split-screen window, a browser sidebar — and the box will overflow, forcing sideways scrolling or cutting off content. That inevitability is why fixed pixel widths should be avoided for structural boxes, even when they seem convenient.

The structural boxes in question are the ones that define the page's shape: the main container, columns, sidebars, card grids, and content areas. Those should be sized with fluid techniques: percentages, flexible grid tracks, flexible flex items, and max-width ceilings. Those techniques describe a relationship to the available space, so they adapt when the space changes. A column defined as 1fr in a grid, or as a percentage of its container, has no width at which it suddenly overflows; it simply narrows, and if it narrows too far, a media query or a wrapping rule can rearrange it.

Fixed pixels still have legitimate uses, but they are for details, not structure. A 1-pixel border, a 2-pixel outline, a 24-pixel icon, a small badge — these are elements whose size is part of their identity and which should not scale with the screen. A button's padding might be in rem rather than pixels, but its border can safely be pixels. The distinction is between "this detail has a fixed size by nature" and "this box must fit whatever screen it lands on." The first is fine in pixels; the second is not.

A useful audit is to search a stylesheet for width declarations in pixels and ask of each one whether it belongs to structure or detail. Structural pixel widths are candidates for replacement with a fluid value or a max-width. You do not need to eliminate every pixel width — that would be dogmatic — but you should be able to justify each one that remains. If you cannot justify it, it is probably a future overflow bug, and replacing it now, while the layout is fresh in your mind, is far cheaper than fixing it after a visitor reports sideways scrolling.

Fixed widths also creep in through third-party content, such as an embedded widget or an advertisement that declares its own pixel size. When a page overflows only on certain pages, check whether an embed or a widget is the wide element, and whether its container can constrain it with max-width: 100% and overflow handling. Third-party code is not an excuse for sideways scrolling, and constraining it at your container boundary is part of owning the page's responsive behaviour.

Check: Which parts of a layout may safely use fixed pixels, and which should not?

Section 40 — Organising breakpoints in your CSS

As a stylesheet grows, its breakpoints can become its messiest part. Queries scattered randomly, duplicated at slightly different widths, or placed far from the components they adjust make the file hard to read and harder to change. A small amount of organisation prevents that, and it pays off every time the design needs updating.

The most effective habit is to keep each component's media queries close to that component's base styles. If a card component is defined in one place in the file, its queries — for two columns, for larger padding, for a different image ratio — should sit immediately below it, not in a separate "responsive" section at the end of the file. That way, when you edit the card, you see its responsive behaviour at the same time, and you are less likely to change the base without updating the query, or vice versa. A future maintainer, opening the file to change the card, will thank you for the same reason.

The second habit is restraint in the number of breakpoints. Two or three well-chosen widths, discovered from your own design's breaking points, beat eight fiddly ones copied from a device list. Each additional breakpoint is another state to test, another interaction with other queries, and another chance for an in-between width to look wrong. If you find yourself adding a breakpoint for a single minor tweak, ask whether a flexible technique — wrapping, auto-fitting, a clamp() value — could handle that size without a query at all. Often it can.

Comments help too. A short comment above each query stating its purpose — "cards go two-up," "navigation collapses," "sidebar moves below content" — turns a bare number into an intention. Numbers alone are forgettable; a year later, nobody remembers why 873 pixels was chosen, but "sidebar moves below content" is immediately clear. Similarly, if your project uses the same breakpoints in many places, consider defining them as custom properties or, in a build setup, as variables, so a change to a breakpoint propagates consistently. Even without a build tool, consistent, commented breakpoints are a major maintainability win.

Organising breakpoints also means documenting them for the team, not just for yourself. A short note at the top of a stylesheet listing each breakpoint and its purpose — for example, 700 pixels for two columns, 1100 for the wide layout — lets a new developer understand the system in a minute rather than reverse-engineering it from scattered queries. That note costs two lines and prevents the common drift where each developer adds a slightly different breakpoint for the same change, slowly fragmenting the design.

Consistency also helps when a breakpoint must change, because one documented value can be updated everywhere instead of hunting for scattered numbers.

Check: Why keep a component's media query next to its base styles?

Section 41 — A mobile-first walkthrough

Putting the chapter's ideas together, here is a complete mobile-first walkthrough for a simple article page. It has a heading, an image, several paragraphs, and a sidebar with related links. The walkthrough has three steps, each building on the last, and the phone layout is finished first — not retrofitted at the end.

Step one is the base stylesheet, written for a phone. The page is a single column: heading, image, text, then sidebar below the article. The container uses the max-width pattern from earlier, so it fills 90% of a phone screen. The image uses max-width: 100% and height: auto, so it never overflows. Type uses rem sizes, with a comfortable line height. Padding is modest, so content is not crowded against the screen edge, but not so generous that it wastes width. At this point, without a single media query, the page is already a complete, usable article on a phone. That completeness is the mobile-first test: if you stopped here, a phone visitor would have everything they need.

Step two adds the first media query, at the width where the design can support two columns — suppose resizing shows that 700 pixels is where the article and sidebar can sit side by side without crowding. The query changes the layout container to a flex row, gives the article the larger share and the sidebar the smaller share, and increases the padding a little. Nothing else changes: the heading, image, and text rules carry through. On a tablet or small laptop, the visitor now sees the article beside its related links, which is a more efficient use of the wider screen.

Step three adds the second query, at 1100 pixels, where the container can widen and the heading can grow. The container's max-width is already handling the width cap, so this query mainly enlarges the heading with a clamp() value and increases section spacing. The result is a desktop page that feels designed for its space, not merely a phone page stretched out. Three steps, two queries, one base — and each step was tested by resizing before the next was added. That sequence is a template you can reuse for almost any page: base first, then one structural query, then one refinement query.

A walkthrough like this also benefits from a written record of the breakpoints you chose and why, because a future change — adding a new section, changing a card's content — may shift a breaking point. If the record says the sidebar query exists because 700 pixels is where the article and sidebar stop crowding each other, a future developer can retest that specific claim rather than guessing. Responsive design is easier to maintain when its decisions are explained, not merely encoded as numbers.

Check: List the three steps of that walkthrough in order.

Section 42 — Content priority on small screens

A small screen forces a choice that a wide screen lets you avoid: what does the visitor need first? On a desktop, a headline, a hero image, a sidebar, related articles, and a newsletter box can all be visible at once, and the visitor can scan among them. On a phone, only a small portion is visible at a time, and the visitor scrolls through the page in order. Whatever comes first in that order gets attention; whatever comes last may never be seen. Content priority is therefore a design decision with real consequences for whether visitors find what they came for.

The practical way to set priority is to order the HTML by importance. Put the main heading and the key message first, then the primary action, then the supporting detail, then the secondary material such as related links. On a phone, that order is the reading order. On a desktop, CSS can rearrange the visual presentation — for example, placing a sidebar beside the article — but the HTML order remains the priority order for anyone who does not see the visual layout. That includes screen reader users, who encounter content in HTML order, and search engines, which weigh early content more heavily. Getting the HTML order right therefore serves more than phone visitors.

A common mistake is to put marketing or decorative material first because it looks impressive on a desktop hero, while the information the visitor actually needs is pushed far down the phone page. A visitor who arrived looking for opening hours, a price, or a download link should not have to scroll past three screens of promotion to find it. Ask, for each page, what the most likely visitor task is, and make sure that task's content and action appear early. If the answer is unclear, the page's purpose itself may need clarifying, which is a content decision, not a CSS one.

Priority also interacts with hiding. If secondary content is hidden on small screens, it should be genuinely secondary — decoration or detail that a phone visitor can do without, or can reach by another route. If content is important enough that hiding it would harm the visitor's task, it belongs in the priority order, stacked below the main content, not removed. That discipline — order by importance, hide only the unimportant — is what keeps a small-screen page both focused and complete.

Content priority also applies to the order in which images and scripts load, because a phone visitor on a slow connection meets the top of the page first. An image or script that blocks the main content, even briefly, delays the very information the visitor came for, while less important material below the fold can safely load later. Prioritising content therefore means both ordering it in the HTML and, where possible, letting the most important resources load first, so the page becomes useful as quickly as possible.

Check: Why does HTML order matter beyond how the page looks?

Section 43 — Responsive embeds: video and maps

Embedded content — videos, maps, social media posts, interactive widgets — arrives with fixed dimensions set by the service that provides it. A video embed might be 560 by 315 pixels, a map 600 by 450. On a desktop those sizes fit comfortably, but on a phone they overflow, forcing sideways scrolling or cutting off the embed's controls. Embeds are therefore a classic source of responsive bugs, and they deserve a specific technique.

The technique uses the aspect-ratio property from earlier in this chapter. Wrap the embed in a container, give the container a fluid width and the correct ratio, and make the inner frame fill the container:

.embed {
  aspect-ratio: 16 / 9;
  width: 100%;
}
.embed iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

The container's width follows its parent, so it is 360 pixels on a phone and 800 on a desktop. Its height follows from the ratio, so it is always widescreen-proportioned. The frame inside fills it completely. The embed never overflows, never distorts, and its controls remain reachable at every size. For a map, which is often squarer, a ratio such as 4 / 3 may suit better; the principle is identical, only the numbers change.

There are two further considerations. First, embeds often load heavy third-party scripts and tracking code, which can slow a phone page considerably. A responsible approach loads the embed only when the visitor scrolls near it, or shows a lightweight preview image that loads the full embed on tap. That lazy approach is a performance improvement as well as a privacy one, and it is worth considering for any page with several embeds. Second, embeds must remain usable: a map that is too small to tap accurately, or a video whose controls are cut off, has not been made responsive merely by fitting on screen. Test embeds at phone width by actually playing the video and interacting with the map, not just by looking at them.

Embeds are a good final test for a responsive page, because they come from outside your control and expose any assumption your layout made about fixed sizes. If your embeds behave at every width, your layout is probably robust; if they overflow, the fix is usually the container pattern above, applied consistently.

Responsive embeds also need a fallback for visitors who cannot load the third-party service, whether because of a network restriction, a privacy tool, or a temporary outage. A short link to the video or map, placed near the embed, ensures the content remains reachable even when the embed itself fails. That link is a small addition, but it turns a broken embed from a dead end into a detour, and it reflects the same principle as the rest of this chapter: the content matters more than the particular way it is presented.

Check: What two rules keep an embedded video proportional on any screen?

Section 44 — Common responsive mistakes

Most responsive failures fall into a small set of familiar mistakes, and learning to recognise them will save you hours of debugging. The first, and most common, is a missing viewport meta tag. Without it, a phone browser shrinks the desktop layout, and even perfect media queries appear broken. If a page looks tiny on a phone but fine on a desktop, check the head for that tag before touching the CSS.

The second is fixed widths on structural boxes. A container, column, or card set to an exact pixel width will overflow the moment a narrower screen arrives. The fix is fluid sizing — percentages, flexible grid and flex values, and max-width ceilings — as taught throughout this chapter. Search a failing stylesheet for pixel widths on layout boxes, and you will often find the culprit immediately.

The third is images without the responsive rule. A photograph that keeps its natural width will burst out of a phone layout, however good the rest of the CSS is. The global rule img { max-width: 100%; height: auto; } should be present in every project, and its absence is a quick check when a page scrolls sideways.

The fourth is text sized only in pixels, ignoring the visitor's font-size preferences, or sized only in viewport units, becoming unreadable at the extremes. Body text belongs in rem, headings can use clamp() with sensible limits, and both should be tested with the browser's default font size increased. Text that ignores reader preferences is not merely a style issue; it is an accessibility failure.

The fifth is breakpoints copied from a device list rather than discovered from the design. Such breakpoints trigger where nothing was broken and miss where something was, producing a stylesheet that is busy yet ineffective. Breakpoints should come from resizing your own page and noting where it strains. If you avoid these five mistakes — viewport tag, fluid structure, responsive images, respectful type, and evidence-based breakpoints — most responsive layouts will work, and the remaining problems will be specific and tractable rather than mysterious.

A sixth mistake, closely related to the fifth, is testing only at device presets and never at the widths in between, which leaves awkward intermediate states undiscovered. A layout can be perfect at 360 and 768 pixels yet broken at 500, where a grid has an orphan or a heading wraps badly. Continuous resizing, not just preset jumping, is the habit that catches those states, and it is worth adding to the list of mistakes to avoid: never assume the widths between your tests are safe without looking at them.

Recognising these patterns early turns debugging from guesswork into a short checklist, which is exactly the skill this chapter aims to build.

Check: Which mistake makes even correct media queries look broken on a phone?

Section 45 — Debugging horizontal scrolling

Sideways scrolling on a phone — where the page can be dragged left and right as well as up and down — is the most visible symptom of a responsive failure, and it almost always means something on the page is wider than the viewport. Debugging it is a systematic hunt for that oversized element, and there is a practical method that works reliably.

Start by confirming the symptom at phone width, either on a real phone or in device mode. Then open developer tools and inspect elements one by one, looking for a box that extends past the right edge of the viewport. Developer tools highlight each element's box as you hover over it in the elements panel, so an oversized box becomes visible as a highlight stretching beyond the screen. Work from the outside in: check the main containers first, then their children, narrowing down until you find the element that is too wide.

The usual suspects are worth knowing. A long unbroken word, such as a URL or a technical term, cannot wrap and will push its container wider; the fix may be to allow breaking or to shorten the text. A fixed-width image or embed, without the responsive rules from this chapter, keeps its natural width. An element with a large fixed margin, or with padding added on top of a percentage width without border-box sizing, can exceed its container. A flex or grid item with a minimum content size larger than its allotted space can also force overflow, in which case a smaller minimum or a wrapping rule helps.

Once you find the element, fix its width rather than hiding the symptom. Reduce a fixed width, add max-width: 100%, allow wrapping, or rearrange the layout at that size. Then retest by resizing and on a real phone, because a fix that works at one width can introduce overflow at another. The discipline here is general: a symptom is not a cause, and a fix that hides a symptom without addressing its cause will reappear, often in a worse form.

Debugging horizontal scrolling also benefits from a process of elimination: temporarily hide sections one at a time, starting with the most complex, and check after each whether the scrolling disappears. When it does, you have found the section containing the wide element, and you can narrow the search within it. That method is slower than inspecting highlights, but it works when the wide element is created by a combination of elements rather than a single obvious box, and it is a useful fallback when inspection is inconclusive.

That method also works when the cause is a combination of small overflows rather than one large element, which inspection alone can miss.

Check: What is the first thing to look for when a page scrolls sideways?

Section 46 — Why overflow-x hidden is a warning sign

When sideways scrolling appears, a tempting quick fix is to add overflow-x: hidden; to the body or the html element, telling the browser to clip anything that extends past the viewport's sides. The sideways scrolling disappears, the page looks tidy, and the problem seems solved. It is not solved; it is hidden, and that distinction matters for several reasons.

First, the oversized element is still there, still wider than the viewport, and its clipped portion is simply invisible. If that portion contained content — the end of a sentence, a button, a part of an image — that content is now unreachable, not merely out of view. A visitor cannot scroll to it, because scrolling in that direction has been disabled. What looked like a layout fix has become a content loss, and the visitor has no way to know what they are missing.

Second, clipping on the body can interfere with accessibility. Keyboard users navigate by focus, and if a focused element lies in the clipped region, the browser may struggle to scroll it into view, leaving the focus indicator invisible. Sticky positioning, which relies on scrolling behaviour, can also break when overflow is hidden on an ancestor. These are subtle failures, but they affect exactly the visitors who most need a predictable page.

Third, overflow-x: hidden on the body can mask a problem that will reappear elsewhere — in a different browser, at a different width, or when content changes. A long word that overflowed today may be replaced by a longer word tomorrow, and the clipping will silently hide more. The page's author, seeing no sideways scrolling, may believe the layout is robust when it is in fact fragile.

There are rare legitimate uses, such as clipping a deliberately overflowing decorative element whose overflow is known and harmless, applied to that element's own container rather than to the whole page. But as a routine fix for sideways scrolling, it is a warning sign: it tells a future maintainer that a real problem was papered over. Find the wide element, fix its width, and reserve clipping for decoration you have consciously chosen.

Clipping with overflow hidden can also hide a focus indicator or a dropdown menu that extends beyond its container, turning a navigation feature into an invisible one. A dropdown that opens downward from a header, for example, may be clipped if an ancestor has hidden overflow, leaving keyboard users able to focus items they cannot see. That is a strong reason to apply overflow clipping narrowly, to a specific decorative container, rather than broadly to the page, where its side effects are hard to predict.

When in doubt, prefer a visible overflow you can investigate over a hidden one you cannot see, because visibility is what makes debugging possible.

Check: Why is overflow-x: hidden on the body usually the wrong fix?

Section 47 — A responsive hero section

A hero section — the large opening block at the top of a page, usually with a heading, a short message, a call to action, and often an image — needs more responsive care than most components, because it is the first thing every visitor sees. If the hero fails on a phone, the visitor's first impression is failure, however good the rest of the page is. Designing it responsively is therefore a priority, not an afterthought.

On a phone, the sensible hero arrangement is stacked and centred. The heading sits at the top, followed by the supporting text, then the button, with the image below or behind at a reduced size. Centring works well here because the narrow column has no room for a side-by-side arrangement, and a centred stack reads as intentional rather than cramped. The heading should use a clamp() size so it is prominent without wrapping over too many lines, and the button should be full-width or comfortably large, so it is easy to tap. The image, if it is decorative, can be smaller or even omitted at the smallest sizes; if it carries meaning, it should sit below the text where it does not push the action off screen.

On a desktop, the same content can sit beside the image: heading, text, and button in one column, image in another, with generous spacing. A single media query typically makes that switch, changing a flex direction from column to row, or a grid from one column to two. The content order in the HTML should remain heading, text, button, image, so that the phone stack and the screen reader order agree, and the desktop visual order is achieved by the layout, not by reordering the markup.

Height deserves care too, as earlier sections warned. A hero that fills the whole viewport on a desktop can swallow a phone screen, hiding the button or the content below. Use a minimum height with comfortable padding rather than a forced full height, or use the dynamic viewport unit with a fallback, and test on a real phone with its toolbars showing and hidden. A hero that introduces the page clearly, shows its action without scrolling, and adapts gracefully from phone to desktop has done its job, and it sets the tone for everything that follows.

A hero's call to action also deserves responsive thought beyond its size: on a phone, the button should lead to the same destination as on a desktop, but it may need a shorter label to fit comfortably, and it should not be the only route to that destination. A visitor who misses the hero button should still find the same action in the navigation or in the content below. Redundancy of important actions, done sparingly, protects visitors who scroll past the hero or whose hero image fails to load.

Check: How does a hero section's arrangement change between phone and desktop in this example?

Section 48 — Responsive design and accessibility together

Responsive design and accessibility are often taught as separate topics, but they overlap deeply, because both are about serving visitors whose situations differ from the designer's own. A page that only works at one size, or that blocks the adaptations visitors need, fails on both counts at once. The most important overlap is zoom: visitors with low vision magnify pages to read them, and a responsive page must support that, not fight it.

The clearest rule is never to disable zoom. The viewport tag should not contain user-scalable=no or a maximum-scale that prevents magnification, because those settings block a basic accessibility tool. Some designers add them to preserve a pixel-perfect layout, but a layout that requires blocking zoom to look right is a layout that needs fixing, not protecting. Let visitors zoom, and make sure the layout reflows sensibly when they do: text should wrap, columns should stack if necessary, and controls should remain reachable. A page that breaks when zoomed to 200% has a responsive problem as well as an accessibility problem, and Chapter 14 returns to that test in detail.

Text resizing is the related habit. Visitors who increase their browser's default font size expect the whole page — type, spacing, and layout — to grow with it. A page built in rem units does that naturally; a page built only in pixels does not, and its text may overflow its boxes when enlarged. Testing with an increased default font size is therefore both a responsive test and an accessibility test, and it should be part of your routine.

Other overlaps include tap targets and focus order. A button that is easy to tap is also easier for a visitor with limited motor control; a focus order that follows the visual order after a layout change serves keyboard users as well as sighted ones. When a media query rearranges a page, check that the tab order still makes sense and that focus indicators remain visible. Responsive design that preserves accessibility at every size is not extra work layered on top of layout; it is layout done properly, with all visitors in mind from the start.

Responsive accessibility also includes testing focus order after each layout change, because a visual rearrangement that moves a sidebar beside an article can change the order in which keyboard users encounter content. If the visual order and the focus order diverge, keyboard users may jump around the page in a confusing sequence, even though sighted users see a logical layout. Checking focus order at each breakpoint, by tabbing through the page, catches that divergence while it is still easy to fix by adjusting HTML order.

That overlap is why accessibility testing belongs in responsive testing, not as a separate phase added at the end of a project.

Check: Why must you never disable zoom in the viewport meta tag?

Section 49 — A responsive checklist before launch

Before a page ships, a short responsive checklist catches problems that are easy to miss during building but embarrassing after launch. Run through it at phone, tablet, and desktop widths, and on a real phone if you possibly can. The checklist below is deliberately short: a checklist that is too long will not be used, while a short one, used every time, prevents most failures.

First, confirm the viewport meta tag is present and does not disable zoom. Second, check for sideways scrolling at phone width, and fix any wide element rather than clipping it. Third, confirm images are responsive — the global max-width rule is in place, and key images use srcset where file size matters. Fourth, read the text without zooming at phone width: is it legible, are lines a comfortable length, and does body text respect an increased default font size? Fifth, test tap targets with your thumb: are buttons and links large enough and spaced apart enough to hit reliably?

Sixth, test navigation at every width: does the menu open and close by touch and by keyboard, and are all links reachable? Seventh, complete the page's key task on a phone — submit the form, follow the link, play the video — rather than merely looking at the page. Eighth, check embeds and tables specifically, because they are the classic overflow sources. Ninth, resize continuously through all widths, watching for strain between breakpoints, not just at them. Tenth, note the results: which widths were tested, which device was used, and what was fixed. That record helps the next person, and it helps you when the page is updated later.

A checklist is not a substitute for judgement, and passing it does not guarantee a perfect page. But a page that passes these ten checks is very unlikely to contain the classic responsive failures — tiny text, sideways scrolling, unreachable navigation, or broken forms — and that is a strong foundation to ship on. Make the checklist a habit, not a one-off, and it will repay itself on every project.

A final checklist habit is to re-run the checklist after any significant content change, not only before first launch. New images, new embeds, new sections, and new third-party widgets can all introduce overflow or performance problems that were absent before. A page that passed the checklist in January may fail it in June after a content update, and the only way to know is to check again. Treating the checklist as a recurring habit, rather than a one-time gate, keeps a site responsive over its whole life.

A short, regularly used checklist beats a long, ignored one, and consistency matters more than comprehensiveness on a busy project.

Check: Name four items from that pre-launch checklist.

Section 50 — Chapter 12 in one paragraph

Responsive design is the practice of building one page that serves many screens well. Its foundation is fluid: percentages and flexible grid and flex sizing let content adapt automatically, a centred container with a maximum width keeps line lengths readable on wide monitors, and relative units let type and spacing respect both the screen and the visitor's preferences. Media queries then make deliberate changes at breakpoints discovered from your own design — stacking into columns, collapsing navigation, rearranging heroes — while responsive images, fluid type with limits, and careful handling of tables, forms, and embeds ensure that every kind of content behaves at every size. Testing completes the practice: resizing continuously, using device mode for quick checks, and verifying on a real phone, with a thumb, on a real connection, before launch. A page built that way does not merely fit a phone and a monitor; it welcomes visitors on both, and on every screen in between, with the same content, the same actions, and the same care. That welcome is the point of the whole chapter, and it is a standard worth holding every page you build to, from now on. That welcome also depends on habits that outlast any single project: starting with the smallest screen, choosing breakpoints from evidence, testing continuously, and fixing causes rather than symptoms. Those habits transfer to every site you build, whatever its subject or its framework, because they are habits of attention to the visitor's actual situation. A developer who practises them will produce responsive pages almost as a side effect, while a developer who only memorises techniques will keep rediscovering the same failures. The techniques in this chapter are the tools; the habits are what make them work reliably, project after project, and they are worth carrying into the next chapters, where motion, variables, and accessibility will add further layers to the same visitor-centred craft. The result is a page that respects its visitors: it does not demand a particular device, a particular connection, or a particular way of seeing, but meets each visitor in their own situation with content that is readable, reachable, and usable. Building that kind of page consistently is not a matter of memorising every property, but of keeping the visitor's situation in mind at each decision, from the first container to the last breakpoint, and testing the result where visitors will actually use it. That standard — one page, many screens, every visitor welcomed — is the measure against which to judge each layout decision, and it rewards the patient work of testing, refining, and testing again. Keep that measure in mind as you build, and let it guide every choice from container widths to image sizes.

Check: In your own words, summarise the three main tools of responsive design.

Practical task

Build a responsive article page with a heading, an image, three paragraphs, and a row of three cards. Start mobile-first: one column, full-width image with max-width: 100%, and the viewport meta tag in place. Add one media query at a width you discover by resizing your browser that turns the cards into a row, and a second that adds a sidebar or widens the container. Test it by dragging the browser narrow and wide, then on your phone, and fix any sideways scrolling before you call it done. Extend the task if you finish early: add a responsive image with srcset, a heading sized with clamp(), and a navigation menu that works by touch and by keyboard, and run through the pre-launch checklist from Section 49, noting anything you had to fix.

Chapter questions

  1. Explain, in plain words, the difference between a fixed width and a fluid width, and when each is appropriate.
  2. Write a media query that changes a navigation list from a column to a row at 700 pixels and wider.
  3. A page looks tiny on a phone but fine on a desktop. What is the most likely missing piece, and how do you fix it?
  4. Why is srcset useful, and when would you choose the <picture> element instead?
  5. Describe how you would test a new page for responsiveness before launching it, including at least one real-device step.