Mobile resilience

Your CSS doesn't know about the notch, the home bar, or the keyboard

## Safe areas ```css .app { padding-top: env(safe-area-inset-top); padding-right: env(safe-area-inset-right); padding-bottom: env(safe-area-inset-bottom); padding-left: env(safe-area-inset-left); } ``` For full-bleed backgrounds, use `viewport-fit=cover` and apply safe-area padding to the content layer: ```html <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" /> ``` ```css .background { /* full-bleed, extends behind the notch */ } .content { padding-left: max(1rem, env(safe-area-inset-left)); padding-right: max(1rem, env(safe-area-inset-right)); padding-bottom: max(1rem, env(safe-area-inset-bottom)); } ``` `max(1rem, env(...))` ensures minimum padding even on devices without insets. Fixed elements at the bottom need explicit inset handling: ```css .bottom-bar { padding-bottom: env(safe-area-inset-bottom); } .fab { bottom: max(1rem, env(safe-area-inset-bottom)); } ``` Without this, the home indicator covers your UI. ## Never disable zoom ```html <meta name="viewport" content="width=device-width, initial-scale=1" /> ``` No `maximum-scale`. No `user-scalable=no`. If your layout breaks under zoom, the layout is the bug. ### Test under zoom 1. Pinch to 200-300% on a phone. 2. Tap form fields, buttons, and links. 3. Overlapping elements, hidden content, or frozen scrolling are bugs. On desktop: Cmd+= to zoom. Anything that clips or overflows is a layout failure. ## `100dvh`, not `100vh` `100vh` includes browser chrome on mobile. `100dvh` adjusts as browser chrome shows and hides: ```css .full-screen { min-height: 100dvh; } ``` Use `min-height`, not `height`. Content that exceeds the viewport should scroll, not clip. ## `text-size-adjust` Mobile Safari auto-scales text in narrow columns: ```css html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; } ``` ## Common mistakes - **No safe-area inset on fixed bottom elements.** Submit button hidden behind the home indicator. - **`user-scalable=no` from old templates.** Audit the viewport meta tag. - **`100vh` on mobile layouts.** Overflows behind browser chrome. Use `100dvh`. - **Forms that break under zoom.** Fixed buttons floating on fields, tooltips clipping. - **Side insets forgotten.** Horizontal safe areas show in landscape. - **`height: 100dvh` without `min-height`.** Content clips instead of scrolling.