Skip to content

fix(mobile): lift the iOS Safari toolbar by the measured chrome overlap - #392

Merged
Ark0N merged 1 commit into
Ark0N:masterfrom
JDProfresh:fix/ios-safari-toolbar-gap
Sep 10, 2026
Merged

fix(mobile): lift the iOS Safari toolbar by the measured chrome overlap#392
Ark0N merged 1 commit into
Ark0N:masterfrom
JDProfresh:fix/ios-safari-toolbar-gap

Conversation

@JDProfresh

Copy link
Copy Markdown

Fixes #391.

Problem

With the phone layout active on iPhone Safari there is an empty band of about 40 CSS px between the bottom toolbar and Safari's bottom bar whenever the bar is expanded, and the terminal is padded by the same amount. The phone block lifts the toolbar by (100vh - var(--app-height)) on iOS Safari to clear a bar that position: fixed elements were assumed to sit behind. On iPhone Safari they already stop above it; 100vh is the large viewport with the bar collapsed and --app-height is the visual viewport with it expanded, so the expression measures the bar's collapsible height instead of an overlap.

Change

updateAppHeight() in mobile-handlers.js now also sets --chrome-overlap to innerHeight - visualViewport.height, the distance the layout viewport that anchors fixed elements extends past the visible area. The two rules in mobile.css (.ios-device.safari-browser .toolbar and .ios-device.safari-browser .main) use that variable in place of 100vh - --app-height. On iPhone Safari the value is 0, so the toolbar meets the bar; on any browser where fixed elements really do land behind the chrome it equals the overlap, so the lift is kept there. The keyboard-visible rules, which already override the toolbar offset, are unchanged, and updateAppHeight() already runs on visual viewport resize and after the keyboard closes, so the value tracks the bar collapsing and expanding.

Independent of #390 (applies cleanly on master), but on a 440pt phone the phone block only matches once #390 is in, so the device check below ran with both.

Verification

  • npm run check:frontend-syntax and npm run format:check: pass
  • npm test on this commit stacked on fix(mobile): raise the phone breakpoint from 430px to 600px #390: 351 files passed, 1 skipped; 6755 tests passed, 12 skipped
  • Playwright WebKit with the iPhone descriptor at 440 to 600px: no console errors, tiers unchanged (headless WebKit has no browser bar, so it cannot show the band itself)
  • Real device, iPhone 17 Pro Max, Safari, 100% zoom: toolbar sits directly on Safari's bar at rest, toolbar and accessory bar sit directly above the keyboard when it is open, the toolbar stays flush while the bar collapses and expands on scroll, and the prompt and status lines stay visible above the toolbar

…ap, not 100vh minus the visual height

The phone block lifted the toolbar (and padded .main) by (100vh - --app-height) on iOS Safari to clear a bottom bar that position: fixed elements were assumed to sit behind. On iPhone Safari fixed elements already stop above the bar, and 100vh is the large viewport with the bar collapsed while --app-height is the visual viewport with it expanded, so the expression measures the bar's collapsible height and shows up as an empty band between the toolbar and the bar whenever the bar is expanded. The terminal was padded by the same amount.

The lift is now --chrome-overlap, set in updateAppHeight() as innerHeight minus the visual viewport height: the distance the layout viewport that anchors fixed elements extends past the visible area. That is 0 on iPhone Safari, so the toolbar meets the bar, and it is the overlap itself on any browser where fixed elements really do land behind the chrome, so those keep the lift. The keyboard-visible rules, which already override the toolbar offset, are unchanged.
@Ark0N
Ark0N merged commit e3d5fd9 into Ark0N:master Sep 10, 2026
@Ark0N

Ark0N commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Merged and shipped in v1.26.2. Thank you for reporting #391 and then fixing it.

Diagnosing 100vh - --app-height as measuring the bar's collapsible height rather than an overlap is the correct reading, and innerHeight minus the visual viewport height is the honest measure of how far the layout viewport that anchors fixed elements extends past the visible area. It is 0 on iPhone Safari, where fixed elements already stop above the bar, and it is the real overlap anywhere they do not, so the lift is kept exactly where it is still needed.

One thing you should know, because it affects your other PRs too: no CI ran on this branch at all. GitHub reported it as MERGEABLE rather than failing, and check-runs came back with total_count: 0, so there was never a green check to read. That is a property of how workflow runs are authorised for your fork, not anything wrong with the PR.

So I validated it locally before merging, in an isolated worktree merged onto current master:

  • PostCSS-parsed mobile.css (Prettier does not catch an unclosed block or a malformed calc())
  • node --check on mobile-handlers.js
  • confirmed no stale 100vh - var(--app-height lift was left behind anywhere in the sheet
  • drove a headless iPhone-shaped context with a faked 60px bottom bar: --chrome-overlap goes 0px to 60px, the toolbar bottom follows, and main padding goes 40px to 100px, with both usages staying inside the .ios-device.safari-browser plus max-width: 430px guard
  • full test gate after the merge: 6803 passed

WebKit cannot launch on this machine, so your real-device check on the iPhone 17 Pro Max is the only evidence for the actual Safari behaviour. Please keep including that in the PR body, it is the part I cannot reproduce.

#390 is still open on purpose. It touches 20 files, has the same missing-CI situation, and by your own note it interacts with this one, which has now changed the phone block underneath it. It deserves its own release rather than riding along with a small one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iOS Safari: empty band between the phone toolbar and Safari's bottom bar

2 participants