fix(v2): pin mobile bottom nav with sticky instead of fixed - #4155
Open
nickybmon wants to merge 3 commits into
Open
fix(v2): pin mobile bottom nav with sticky instead of fixed#4155nickybmon wants to merge 3 commits into
nickybmon wants to merge 3 commits into
Conversation
iOS Safari has a known engine bug where position: fixed elements can lose their correct viewport anchor during and after a scroll gesture, leaving BottomNav visually detached from the bottom edge. Forcing a relayout doesn't clear it, even synchronously and on-demand, which points to a stale internal reference the page can't invalidate. Switch BottomNav to position: sticky inside a full-height, non-flow anchor (flex-end aligned), so its position is computed through the ordinary layout pipeline instead of the buggy fixed-to-viewport path. The anchor doesn't contribute to its parent's height (same as the old fixed element didn't), so no other view's bottom-nav clearance math needs to change.
Shorten the two comments added by the sticky fix to a plain why, instead of narrating the debugging steps that found the bug.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
On iOS Safari, the v2 mobile bottom nav (
BottomNav.vue) could visually detach from the bottom of the screen during and after scrolling, ending up stuck floating mid-screen instead of pinned to the bottom edge. This reproduced consistently on a real iPhone across multiple pages (Home, Settings, Gallery, Game Details) but never in a resized desktop Safari window.Root cause: iOS Safari has a known engine-level issue where
position: fixedelements can lose their correct viewport anchor during a scroll gesture and never properly reset, even after scrolling stops. On-device debugging (via Web Inspector) confirmed the element's layout box was frozen at a stale offset — and critically, this persisted even under a manually forced, synchronous relayout (togglingdisplayoff/on), which normally forces a fresh layout pass in any browser. That ruled out a page-level CSS/JS fix aimed atposition: fixeditself.The fix switches
BottomNav.vuefromposition: fixedtoposition: sticky, wrapped in a full-height, non-flow-affecting anchor (position: absolute; inset: 0withflex-direction: column; justify-content: flex-end) so the pill's natural (un-stuck) position sits at the bottom of the full page height.position: stickyis computed through the ordinary layout pipeline rather than the separate fixed-to-viewport mechanism, so it isn't subject to the same bug. The anchor doesn't contribute to its parent's layout height (same as the oldfixedelement didn't), so no other view's bottom-nav clearance calculations needed to change.Note:
AppNav.vue(the top nav) still usesposition: fixedand was intentionally left unchanged — it isn't meant to behave like a sticky element, and there's no evidence it has the same issue.AI assistance disclosure
This PR was developed with Claude Code: diagnosing the bug (including live on-device debugging via Safari Web Inspector) and implementing/iterating on the fix were done in collaboration with Claude, with the author driving device testing and reviewing/directing each step.
Testing
npm run typecheck, ESLint, Prettier,npm run test(636/636 passing), andnpm run buildall pass.Checklist
Screenshots (if applicable)
N/A