responsive-design.md

  1# Responsive Design
  2
  3## Mobile-First: Write It Right
  4
  5Start with base styles for mobile, use `min-width` queries to layer complexity. Desktop-first (`max-width`) means mobile loads unnecessary styles first.
  6
  7## Breakpoints: Content-Driven
  8
  9Don't chase device sizes; let content tell you where to break. Start narrow, stretch until design breaks, add breakpoint there. Three breakpoints usually suffice (640, 768, 1024px). Use `clamp()` for fluid values without breakpoints.
 10
 11## Detect Input Method, Not Just Screen Size
 12
 13**Screen size doesn't tell you input method.** A laptop with touchscreen, a tablet with keyboard. Use pointer and hover queries:
 14
 15```css
 16/* Fine pointer (mouse, trackpad) */
 17@media (pointer: fine) {
 18  .button { padding: 8px 16px; }
 19}
 20
 21/* Coarse pointer (touch, stylus) */
 22@media (pointer: coarse) {
 23  .button { padding: 12px 20px; }  /* Larger touch target */
 24}
 25
 26/* Device supports hover */
 27@media (hover: hover) {
 28  .card:hover { transform: translateY(-2px); }
 29}
 30
 31/* Device doesn't support hover (touch) */
 32@media (hover: none) {
 33  .card { /* No hover state - use active instead */ }
 34}
 35```
 36
 37**Critical**: Don't rely on hover for functionality. Touch users can't hover.
 38
 39## Safe Areas: Handle the Notch
 40
 41Modern phones have notches, rounded corners, and home indicators. Use `env()`:
 42
 43```css
 44body {
 45  padding-top: env(safe-area-inset-top);
 46  padding-bottom: env(safe-area-inset-bottom);
 47  padding-left: env(safe-area-inset-left);
 48  padding-right: env(safe-area-inset-right);
 49}
 50
 51/* With fallback */
 52.footer {
 53  padding-bottom: max(1rem, env(safe-area-inset-bottom));
 54}
 55```
 56
 57**Enable viewport-fit** in your meta tag:
 58```html
 59<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
 60```
 61
 62## Responsive Images: Get It Right
 63
 64### srcset with Width Descriptors
 65
 66```html
 67<img
 68  src="hero-800.jpg"
 69  srcset="
 70    hero-400.jpg 400w,
 71    hero-800.jpg 800w,
 72    hero-1200.jpg 1200w
 73  "
 74  sizes="(max-width: 768px) 100vw, 50vw"
 75  alt="Hero image"
 76>
 77```
 78
 79**How it works**:
 80- `srcset` lists available images with their actual widths (`w` descriptors)
 81- `sizes` tells the browser how wide the image will display
 82- Browser picks the best file based on viewport width AND device pixel ratio
 83
 84### Picture Element for Art Direction
 85
 86When you need different crops/compositions (not just resolutions):
 87
 88```html
 89<picture>
 90  <source media="(min-width: 768px)" srcset="wide.jpg">
 91  <source media="(max-width: 767px)" srcset="tall.jpg">
 92  <img src="fallback.jpg" alt="...">
 93</picture>
 94```
 95
 96## Layout Adaptation Patterns
 97
 98**Navigation**: Three stages: hamburger + drawer on mobile, horizontal compact on tablet, full with labels on desktop. **Tables**: Transform to cards on mobile using `display: block` and `data-label` attributes. **Progressive disclosure**: Use `<details>/<summary>` for content that can collapse on mobile.
 99
100## Testing: Don't Trust DevTools Alone
101
102DevTools device emulation is useful for layout but misses:
103
104- Actual touch interactions
105- Real CPU/memory constraints
106- Network latency patterns
107- Font rendering differences
108- Browser chrome/keyboard appearances
109
110**Test on at least**: One real iPhone, one real Android, a tablet if relevant. Cheap Android phones reveal performance issues you'll never see on simulators.
111
112---
113
114**Avoid**: Desktop-first design. Device detection instead of feature detection. Separate mobile/desktop codebases. Ignoring tablet and landscape. Assuming all mobile devices are powerful.