2019–2026 all devices 320px → 2560px also via MCP

Responsive & multi-device best practices

Seven years of device churn distilled into the rules that survive it: real viewport sizes, breakpoints, touch targets, safe areas, viewport units, performance budgets, and a testing matrix — with the Skynet UI feature that implements each one. Agents can pull this same guide with the MCP get_best_practices tool.

TL;DR checklist

  • Design mobile-first from 320px up; no horizontal scroll at any width from 320 to 2560.
  • Content-driven breakpoints, not device names — here: sm 640 / md 768 / lg 1024 / xl 1280 / 2xl 1536.
  • Body text 16px minimum (also stops iOS zoom-on-focus); never disable pinch zoom.
  • Touch targets 44×44px (Apple 44pt / Material 48dp; WCAG 2.2 AA floor is 24×24).
  • viewport-fit=cover + env(safe-area-inset-*) for notches, Dynamic Island, home indicators.
  • Full-height layouts use 100svh or 100dvh — never bare 100vh on mobile.
  • Images: srcset/sizes, AVIF/WebP, explicit aspect-ratio, lazy-load below the fold, fetchpriority="high" on the LCP image.
  • Core Web Vitals at p75 mobile: LCP ≤ 2.5s · INP ≤ 200ms · CLS ≤ 0.1.
  • Respect prefers-color-scheme, prefers-reduced-motion, prefers-contrast.
  • Test 320, 360, 390, 412, 768, 1024, 1280, 1440, 1920 + one foldable inner screen (~800–900) + both orientations.

How we got here

What actually changed, year by year. The through-line: design for ranges, not devices.

2019
Mobile-first becomes literal
Google's mobile-first indexing turns default; prefers-color-scheme ships and dark mode becomes a requirement; the first Galaxy Fold (768px inner) arrives; 360×640 is the world's top mobile viewport.
2020
Performance gets metrics
Core Web Vitals announced (LCP/FID/CLS); native loading="lazy" lands; mobile passes half of global traffic for good.
2021
Vitals start ranking
Core Web Vitals become a ranking signal; CSS aspect-ratio ships and kills the padding-hack era of layout-shift prevention.
2022
The 100vh problem gets fixed
svh/lvh/dvh ship (Safari 15.4, Chrome 108); the Dynamic Island makes viewport-fit=cover + safe-area insets mainstream; 390–393px becomes the iPhone norm.
2023
Components get their own queries
Container queries reach every engine; :has() goes cross-browser; WCAG 2.2 lands with the 24×24px AA target-size floor.
2024
INP replaces FID
Core Web Vitals swap first-input delay for worst-interaction latency; the Popover API goes Baseline; foldables settle on ~350–430 cover / ~750–930 inner screens.
2025
Three viewports rule mobile
svh/dvh reach Baseline Widely Available; 360×800, 390×844 and 393×852 come to dominate mobile traffic.
2026
Fragmentation is permanent
1920×1080 serves over half of desktop sessions; on mobile the top five viewports cover only ~35% of traffic — the rest spreads across hundreds of sizes.

Device & viewport reference

CSS pixels (what media queries see), not hardware pixels. Phones render at 2–3× DPR — serve 2× imagery and SVG icons; never read screen.width for layout.

Phones (portrait width)

WidthDevicesNotes
320iPhone SE (1st gen), small/older AndroidsThe floor. Everything must work here.
360Samsung Galaxy A/S, most budget AndroidsSingle most common mobile width worldwide.
375iPhone SE 2/3, 6–8, X, 11 Pro, 12/13 miniStill huge in the installed base.
390iPhone 12–14, 15Top-three worldwide.
393Pixel 5–9, iPhone 14 Pro–16Top-three worldwide.
402–412iPhone 16 Pro (402); Pixel XL & many Androids (412)
414iPhone 6–8 Plus, XR, 11
428–440iPhone Pro Max / Plus modelsLargest mainstream phones.

Foldables

StateWidth rangeExamples
Folded (cover)~320–430Z Flip, Z Fold cover screens
Unfolded (inner)~717–928Galaxy Fold 768 → Fold2 884 → recent Folds 900+
Treat the inner screen as a small tablet and the cover as a narrow phone. A continuous 320→1536 layout plus container queries covers both states and the mid-fold near-square (~720) case — never hard-code to one width.

Tablets

WidthDevices
744iPad mini (portrait)
768Classic iPad (portrait) — still the canonical tablet test width
810–834iPad 10.2/10.9, Air, Pro 11 (portrait)
1024iPad Pro 12.9 portrait; classic iPad landscape
1080–1366Tablet landscape widths

Laptops & desktops

WidthContext
1280Small laptops, split-screen desktop windows
1366Budget laptops (long-time #2 desktop size)
1440MacBook Pro default scaled resolution
15361920 hardware at Windows 125% scaling — extremely common
1920Majority desktop size in 2026
2560+Growing fast; cap content width so lines stay readable

Breakpoints that work

Mobile-first, min-width only

Style the 320px layout as the default and add complexity upward. Overriding desktop styles back down is how bugs breed.

Break where content breaks

The five-stop scale tracks real clusters: phones <640, large phones 640, tablets/foldables-open 768, laptops 1024, desktops 1280, large 1536.

Be fluid between stops

Percentages, minmax(), flex-wrap, clamp() — a layout should never depend on landing exactly on a breakpoint.

Components query their container

A card in a sidebar and the same card full-width need @container, not @media — cross-browser since 2023.

<!-- The whole responsive-grid story in one line -->
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4">…</div>

<!-- Zero-media-query card reflow -->
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr)); }

Skynet UI's variants map to 640 / 768 / 1024 / 1280 / 1536; .sk-container caps and centers content; .hide-mobile / .hide-desktop split at 768.

Touch & pointer targets

StandardMinimumStatus
WCAG 2.2 — 2.5.8 Target Size24×24px (or equivalent spacing)Level AA — the legal floor
WCAG — 2.5.5 Target Size (Enhanced)44×44pxLevel AAA
Apple Human Interface Guidelines44×44ptPlatform guidance
Material Design48×48dpPlatform guidance

Typography & spacing

h1 { font-size: clamp(1.75rem, 1.2rem + 2.5vw, 3rem); }
p  { max-width: 65ch; line-height: 1.5; }

Layout foundations

The viewport meta & safe areas

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
.app-shell { min-height: 100vh; min-height: 100svh; }  /* fallback + fix */
.sk-navbar { padding-top: env(safe-area-inset-top); }
.footer-bar { padding-bottom: env(safe-area-inset-bottom); }

Media

Performance budgets

Core Web Vitals, measured at the 75th percentile on mobile.

LCP
≤ 2.5s
Largest Contentful Paint — server time, blocking CSS/JS, hero weight
INP
≤ 200ms
Interaction to Next Paint — long tasks, heavy hydration (replaced FID in 2024)
CLS
≤ 0.1
Cumulative Layout Shift — unreserved media, late fonts, injected banners

Dark mode, motion & user preferences

The testing matrix

WidthRepresents
320Absolute floor (iPhone SE 1, small Androids)
360Most common Android
390–393Modern iPhone / Pixel
412Large Android
768Tablet portrait / foldable inner (small)
820–900iPad Air portrait / foldable inner (large)
1024Tablet landscape / small laptop
1280Laptop
1440Desktop
1920Majority desktop

Beyond widths: both orientations on phone and tablet; a keyboard-only pass (tab order, visible focus, no traps); 200% browser zoom (WCAG 1.4.10 reflow); coarse-pointer emulation; dark and light schemes; reduced motion on; and a real mid-range Android over cellular at least once per release.

Applying this with Skynet UI

PracticeSkynet UI feature
Mobile-first breakpointssm: 640 / md: 768 / lg: 1024 / xl: 1280 / 2xl: 1536 variants
Capped content width.sk-container (fluid: .sk-container-fluid)
Responsive gridsgrid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 + gap-*
Nav that fits every width.sk-navbar — burger <768px, one-row scroll for overflow above
Wide tables.sk-table-wrap wrapper
Touch targets.sk-btn ≥ 44px; :focus-visible styled everywhere
Show/hide by device.hide-mobile / .hide-desktop (768px boundary)
Dark mode & themes9 themes, data-theme, dark-first tokens; MCP make_theme
Contrast checksMCP check_contrast (WCAG ratios)
Icons at any DPR640 inline SVG icons, 1em, currentColor
Validate generated markupMCP validate_markup / npx skynet-ui check

For agents: this guide over MCP

The full guide is available from the Skynet UI MCP server at https://skynetui.com/mcp:

  • Tool get_best_practices — the whole guide, or one section via the optional section argument (e.g. "touch", "viewport", "testing").
  • Resource skynetui://best-practices — the same document as markdown.
curl -s https://skynetui.com/mcp -X POST -H 'Content-Type: application/json' -d '{
  "jsonrpc":"2.0","id":1,"method":"tools/call",
  "params":{"name":"get_best_practices","arguments":{"section":"touch"}}
}'

Stats from StatCounter global data and platform documentation (Apple HIG, Material Design, W3C WCAG 2.2, web.dev Core Web Vitals), current as of 2026. Markdown source: /best-practices.md.