An iOS Home Screen web app with a translucent status bar is short by the bar's height, and only growing the root element fixes it
Fact
With apple-mobile-web-app-status-bar-style: black-translucent and viewport-fit=cover, a page opened from the iOS/iPadOS Home Screen starts under the status bar, yet the initial containing block, 100%, inset: 0 and fixed elements all end env(safe-area-inset-top) short of the bottom, leaving an empty strip. Measured on iPadOS 26: page 802 on an 834 screen, inset 32; 100vh was shorter still (777), and (display-mode: standalone) did not match at all (no manifest, only the apple meta tag).
Why it matters
The obvious fixes fail. A display-mode media query never applies; 100vh makes it worse; fixed layers given calc(100% + inset) are laid out to the bottom but still not painted past the strip. Growing html does paint to the bottom, and fixed elements' containing block grows with it, so growing both adds the gap twice and pushes bottom UI off screen.
How to apply
- Detect with
navigator.standalone === true, notdisplay-mode. - Grow only the root:
html { height: calc(100% + var(--gap, 0px)) }, leave fixed layers atinset: 0. - Set
--gapfrom JS: reset it to 0, measure aposition: fixed; inset: 0probe carryingpadding-top: env(safe-area-inset-top), and use the inset only when screen height minus the probe's height equals it (and the probe spans the screen's width, so split view is left alone). Re-run onresize. Measuring with the gap applied feeds back on itself. - Verify on a device: desktop Chrome cannot emulate standalone or the insets.