Responsive Patterns and Testing
IntermediateNavigation, tables and forms are where responsive designs actually break. Each has a known set of solutions, and each needs testing on a real device rather than a resized window.
Overview
Most responsive CSS is straightforward until it meets the three components that genuinely need a different design at different sizes: a navigation bar that cannot fit eight links on a phone, a table with eight columns, and a form whose labels sit beside its fields. Beyond the patterns, the recurring lesson is that a narrow desktop window is not a phone — it has a mouse, a keyboard, no on-screen keyboard covering half the viewport, and a much faster processor. Testing on a real mid-range Android surfaces problems that DevTools never will.
Navigation
The most common responsive component, and the accessibility parts people skip.
/* Base: the phone. A toggle and a hidden panel. */
.nav-toggle { display: block }
.nav-list { display: none }
.nav-list[data-open] { display: flex; flex-direction: column }
@media (min-width: 48rem) {
.nav-toggle { display: none }
.nav-list { display: flex; flex-direction: row; gap: 1.5rem }
}
<!-- The toggle must announce its state, and control the panel -->
<button class="nav-toggle" aria-expanded="false" aria-controls="nav-list">
<span class="sr-only">Menu</span>
<svg aria-hidden="true">…</svg>
</button>
<ul id="nav-list">…</ul>
/* When the drawer is open: trap focus inside it, close on Escape,
return focus to the toggle, and lock body scroll. A drawer that
leaves focus behind it is a keyboard trap in reverse — the user
tabs into a menu they cannot see. */
/* Alternatives to a hamburger, both often better:
- a visible row that scrolls horizontally
- the priority+ pattern: show what fits, "More" for the rest
A hamburger hides navigation, which measurably reduces its use. */Forms and Touch
The details that only show up on a real phone.
/* Labels above fields on a phone; beside them when there is room */
.field { display: grid; gap: .25rem }
@media (min-width: 48rem) {
.field { grid-template-columns: 12rem 1fr; align-items: baseline }
}
/* iOS zooms the page in when a font smaller than 16px is focused.
The fix is the font size, not a viewport that blocks zoom. */
input, select, textarea { font-size: 1rem }
<meta name="viewport" content="width=device-width, initial-scale=1">
/* NEVER user-scalable=no or maximum-scale=1 — it blocks zoom,
which is an accessibility failure and a WCAG violation. */
/* Touch targets: 44x44px minimum (Apple), 48dp (Android) */
.button, .nav a { min-height: 44px; display: grid; place-items: center }
/* Spacing between targets matters as much as their size. */
/* Full-width primary actions on a phone, within reach of a thumb */
@media (max-width: 40rem) { .form__submit { width: 100% } }
/* The on-screen keyboard covers roughly half the viewport, so a
fixed bottom bar can sit on top of the field being typed into.
dvh plus the virtual keyboard API is the current answer. */Testing
What DevTools shows you, and what only a device will.
/* In DevTools:
- device toolbar for widths, and throttle CPU to 4x and the
network to Slow 4G — that is the actual experience for many
Indian users
- zoom the browser to 200% and confirm nothing is cut off
(WCAG requires usability at 200%)
- set the base font to 24px in browser settings and check the
layout still holds — this is what px-only sizing fails */
/* What DevTools cannot show:
- the on-screen keyboard covering the viewport
- real touch accuracy and thumb reach
- actual scroll performance on a mid-range CPU
- iOS Safari's viewport and 100vh behaviour
- how it looks in bright sunlight */
/* Test on a real device over the local network */
npm run dev -- --host
// then open http://192.168.x.x:3000 on the phone
// Chrome remote debugging: chrome://inspect for a connected Android
/* The rule of thumb: if the product is for Indian students, the
reference device is a ₹12,000 Android on 4G, not a MacBook. */Key Points to Remember
- 1A navigation toggle needs aria-expanded, aria-controls, focus management and Escape — the CSS is the easy half
- 2Inputs below 16px make iOS zoom the page; fix the font size rather than blocking zoom
- 3user-scalable=no is a WCAG violation — never disable pinch zoom
- 4Touch targets need roughly 44px and spacing between them, and primary actions belong within thumb reach
- 5Throttle CPU and network, test at 200% zoom, and verify on a real mid-range Android — DevTools cannot show the on-screen keyboard or true scroll performance
Interview Questions
Sign in to ask AriaWhat does a hamburger menu need beyond showing and hiding a list?
Why does iOS zoom in when a user focuses an input, and how do you fix it properly?
What can you not test by resizing a desktop browser window?
Ask Aria about Responsive Patterns and Testing
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.