Skip to content

Responsive Design

A UX principle for coding agents. Also covers breakpoints, mobile first, reflow, small screens, zoom.

Responsive design is about content, not devices. The instinct to target "iPhone," "iPad," and "desktop" is the wrong frame: there are too many screen sizes to chase, and the ones you pick will be obsolete in a year. Design for the content instead. A layout breaks at the width where its content stops working, and that's where the breakpoint belongs, regardless of which device happens to live near that width.

This doc is the cross-device continuum. The iOS-native, layered-composition side of responsiveness lives in mobile-patterns.md (bottom sheets, split views, contextual menus); the responsive navigation mechanics live in navigation.md; the mobile browser's own defaults live in mobile-web.md (viewport units, safe areas, tap and scroll behavior). This doc covers the principles that span everything from a 320px phone to an ultrawide monitor, and it leans on those siblings rather than repeating them.

Breakpoints Are Content Decisions

A breakpoint is a point where you change the layout because the current one stopped serving the content. It is not a device boundary.

  • Add a breakpoint when the design breaks, not at a device width. Widen the browser until the line length gets uncomfortable, the columns get cramped, or the whitespace turns into a desert. That's a breakpoint. The number is whatever the content dictates.
  • Think in ranges, not targets. "Narrow / medium / wide" beats "phone / tablet / desktop" because it frees you from a device that may not exist and forces you to design for the in-between sizes where most users actually are.
  • Most layouts need only a handful of breakpoints. Each one is a maintenance cost and a place for bugs. Don't add a breakpoint per device; add the few the content genuinely needs.

The rule: let the content set the breakpoints. If it reads and works at every width between your breakpoints, you have the right ones.

Mobile-First, Progressive Enhancement

Start from the narrowest viewport and add complexity as space appears. Designing wide-first and then cramming everything into a phone is how features get hidden and hierarchies collapse.

  • The narrow layout forces you to prioritize: what's essential survives, what's decorative gets cut or deferred. That clarity then benefits the wide layout too.
  • Build up with min-width media queries, layering on multi-column structure, denser information, and secondary surfaces as the viewport grows.
  • Wide screens are an opportunity, not an obligation. You don't have to fill the extra space (see ui/layout-spacing.md — You Don't Have to Fill the Whole Screen); give content a max-width and let the margins breathe.

Fluid Over Fixed

Between breakpoints, prefer layouts that flex with the viewport over ones that snap at fixed sizes. Fluid space absorbs the dozens of widths your breakpoints don't name.

  • Use fluid containers, flexible grids, and clamp() for values that should scale smoothly (gutters, section padding, hero type) so the layout breathes between breakpoints instead of jumping.
  • But size individual elements absolutely, not in percentages. A card or button sized as a percentage becomes too large on desktop and too small on mobile; use absolute sizes (px, rem) and adjust them at breakpoints (see ui/layout-spacing.md — Relative Sizing Doesn't Scale). The container can be fluid while the elements inside it are fixed.
/* Fluid section padding that scales between a floor and ceiling */
.section { padding-inline: clamp(1rem, 5vw, 4rem); }

/* Element sizes stay absolute, adjusted per breakpoint — not percentages */
.card { width: 20rem; }
@media (min-width: 60rem) { .card { width: 24rem; } }

Reflow, Don't Shrink

When space runs out, restack the content; don't squeeze it. Shrinking everything proportionally produces a tiny, unusable copy of the desktop layout.

  • Stack columns vertically at narrow widths. A sidebar-plus-main split becomes sidebar-above-main, or the sidebar collapses into a drawer (see navigation.md — Responsive Navigation).
  • Reorder by priority when stacking. The most important content comes first in the narrow flow, even if it sits second on the wide layout. CSS order and grid placement let visual order diverge from source order, but keep the DOM order sensible for keyboard and screen-reader users.
  • Don't force equal columns. A 1/3 + 2/3 split on desktop can become a single column on mobile; grids are a guide, not a constraint (see ui/layout-spacing.md — Grids are Overrated).

Touch vs Pointer

Input is a spectrum, not a binary tied to screen size. A large touchscreen exists; a small window on a desktop exists. Adapt to the input, not the assumed device.

  • Detect capability, not width. Use @media (hover: hover) and (pointer: fine) for pointer-only affordances like hover states, and treat coarse-pointer (touch) as the baseline (see interactions.md — Hover States on Touch Devices).
  • Size hit targets for touch: at least 44×44px on touch, 24×24px minimum on pointer (see interactions.md — Minimum Sizes, and review-rules.md — Touch targets under 44×44px). When the visual target is smaller, expand the hit area with padding or a pseudo-element (see interactions.md — Hit Area Expansion).
  • Inputs need font-size: 16px or larger on mobile to stop iOS Safari from auto-zooming on focus (see interactions.md — Mobile Input Zoom Prevention).
  • Set touch-action: manipulation on interactive controls to kill the 300ms double-tap-zoom delay (see interactions.md — Prevent Double-Tap Zoom).
  • Size full-height layouts in dvh or svh, never vh. On a phone 100vh is taller than the visible area, so the bottom of the layout hides under the address bar (see mobile-web.md, A 100vh Layout Is Taller Than the Screen).

Responsive Typography

Type carries readability, and readability is where responsiveness most often fails. The constraints don't change with the viewport; the values do.

  • Hold line length at 45–75 characters at every width. On wide screens this means capping text width with a max-width, not letting paragraphs stretch edge to edge (see ui/typography.md — Keep Your Line Length in Check).
  • Scale heading sizes at breakpoints, but keep the jumps meaningful (~25% minimum between distinct roles), and use px/rem, never em, so sizes don't compound through nesting (see ui/typography.md — Establish a Type Scale).
  • Don't shrink body text below comfortable reading size on mobile. Small screens tempt you to cram; resist. 16px body is a floor, not a target.
  • text-wrap: balance on headings prevents orphaned words as the heading reflows across widths (see ui/typography.md — Use text-wrap: balance for Headings).

Tables on Small Screens

Tables are the hardest thing to make responsive, because a table's value is the grid of relationships that a narrow screen can't hold. Pick a strategy deliberately rather than letting the table overflow silently.

  • Horizontal scroll keeps the table intact and lets the user pan. Best when comparing across columns matters and the columns can't be dropped. Make the scroll obvious (a fade edge, a visible scrollbar) and pin the first column as a label anchor.
  • Stacked cards turn each row into a labeled card (label: value pairs). Best when each row is really a record the user reads one at a time, not a grid they scan across.
  • Priority columns hide less-important columns at narrow widths, revealing them via expansion or on wider screens. Best when a few columns carry the meaning and the rest are detail.
  • Don't just let the table cause a horizontal page scrollbar by accident; that's the failure mode, not a strategy. A table is a place to combine data and description and use color for status rather than force everything into uniform sortable columns (see ui/polish.md — Think Outside the Box, Tables).

Images & Media

Media is heavy and dimensionally unpredictable, so responsiveness here is about serving the right size and reserving the right space.

  • Serve appropriately-sized assets with srcset/sizes so a phone doesn't download a desktop-resolution image. Don't scale a small icon up or a huge photo down in the browser (see ui/images.md — Everything Has an Intended Size).
  • Reserve space with aspect-ratio (or width/height attributes) so images don't cause layout shift as they load. A reflow when the image arrives is jarring and hurts perceived performance.
  • Use object-fit: cover to handle unpredictable user-uploaded dimensions gracefully, with a consistent container and a fallback for missing media (see ui/images.md — Beware User-Uploaded Content).
  • Cap media at max-width: 100% so nothing overflows its container and triggers a horizontal scrollbar (see ui/polish.md — Debugging Layout Overflow).

Density Adapts to Surface

The right spacing rhythm isn't one value across all screens. Touch wants more room; a data-dense admin view wants less; a marketing page wants the most.

  • Touch surfaces need looser spacing than pointer ones, because fingers are blunter than cursors and the hit targets are larger.
  • Match density to the surface, not just the width: marketing pages afford generous spacing, forms want moderate, dense admin tables want tight but legible (see ui/layout-spacing.md — Surface-appropriate density). A phone admin table can stay denser than a phone marketing page.
  • Keep internal spacing tighter than external spacing at every size, so groups stay legible as the layout reflows (see ui/layout-spacing.md — Spacing Expresses Relationships).

Layered Compositions at Every Size

The principle that keeps responsive UIs coherent is the same one that makes them feel native: keep context visible whenever you can, at every breakpoint.

  • On phones, a centered modal often becomes a bottom sheet, and a pushed screen often becomes an inline expansion or a sheet, so the parent context stays visible (see mobile-patterns.md — Prefer Layered Compositions Over Full Screens; dialogs.md — Sizing & Responsiveness).
  • At tablet width and above, sheets become side sheets or popovers, and push navigation can become a split view, using the extra horizontal room to show master and detail at once (see mobile-patterns.md — Tablet & larger breakpoints).
  • The constant across sizes: prefer a layer over a teleport. The breakpoint changes the shape of the layer (sheet, popover, split pane), not the principle.

Don't Break Zoom & Reflow

Responsiveness includes the user's own adaptations. Many users zoom or enlarge text, and the layout must survive it.

  • Never disable zoom. No user-scalable=no and no maximum-scale=1 in the viewport meta; both block users who need to magnify (see interactions.md — Respect Browser Zoom).
  • Content must reflow without horizontal scrolling at 320px width, and at 400% zoom, per WCAG 1.4.10 (Reflow). A layout that only works above a certain width fails users who zoom or use small viewports.
  • Respect text resizing (WCAG 1.4.4): the layout shouldn't clip or overlap when the user bumps their default font size up. Test with a larger browser default (see ui/typography.md — Detecting the Browser Default Font Size).

Testing Across Sizes

A responsive layout is only as good as the widths you actually checked. The bugs hide in the in-between sizes and under zoom.

  • Test the continuum, not three snapshots. Drag the browser from narrow to wide and watch for the widths where the layout breaks; those are missing breakpoints.
  • Test on real touch devices, not just an emulator, to catch hit-target, hover, and scroll issues that only manifest with a finger.
  • Test at 200% and 400% zoom and with a larger default font size, to catch reflow and clipping failures.
  • Hunt overflow with the outline trick when a stray horizontal scrollbar appears: * { outline: 1px solid red } reveals the element sticking past the viewport without shifting layout (see ui/polish.md — Debugging Layout Overflow).

Checklist

Breakpoints & layout

  • Breakpoints set by content, not device widths
  • Mobile-first: build up with min-width, prioritizing essentials
  • Fluid containers/spacing (clamp()), but absolute element sizes (no % sizing)
  • Reflow by stacking and reordering, never proportional shrinking
  • Unequal columns allowed; grids are a guide

Input & type

  • Adapt to input capability (hover/pointer), not assumed device
  • Hit targets ≥ 44px touch / ≥ 24px pointer; input font ≥ 16px on mobile
  • touch-action: manipulation on controls
  • Full-height layouts sized in dvh / svh, not vh
  • Line length 45–75 chars at every width; type in px/rem, not em
  • Body text not shrunk below comfortable size on mobile

Content

  • Tables use a deliberate strategy (scroll / stacked cards / priority columns), never accidental overflow
  • Images served via srcset/sizes, space reserved with aspect-ratio, capped at max-width: 100%
  • Density matched to surface and input, not one rhythm everywhere
  • Context kept visible via layers (sheet/popover/split view) at each size

Resilience & testing

  • Zoom never disabled; reflows at 320px and 400% zoom (WCAG 1.4.10)
  • Survives larger default font size (WCAG 1.4.4)
  • Tested across the continuum, on real touch devices, and under zoom

Use this guidance in your coding agent

Install the Better Design MCP once. Your agent then loads this page with one call.

get-ux-principle({ topic: "responsive" })
claude mcp add --scope user better-design --transport http https://better-design.com/api/mcp --header "Authorization: Bearer <YOUR_API_KEY>"
Browse related design systems