iOS Chrome: position:fixed bottom bar and sticky header scroll with page on first load
07:22 18 May 2026

Problem

On iOS Chrome (26), my position: fixed; bottom: 0 tab bar and position: sticky; top: 0 header both scroll with the page content instead of staying
pinned. The entire viewport appears to shift — fixed/sticky elements move together with the content when the browser's bottom toolbar collapses during
scroll.

Key observations

  • Only affects certain pages — /product/*, /shop, /cart work perfectly fine, even on first load
  • First load only — if I reload the page, the bug sometimes persists. But after navigating to a working page (e.g. /product/...) via client-side
    navigation and coming back, the bug disappears permanently for that session
  • Opening a working page in another tab in the same incognito session fixes the bug for all tabs
  • Not reproducible in desktop browsers or Playwright (WebKit emulation)
  • Not reproducible in iOS Safari

What I've tried (none worked)

CSS approaches:

  • transform: translateZ(0) / will-change: transform on the fixed element
  • position: sticky instead of position: fixed
  • top: calc(100dvh - height) instead of bottom: 0
  • overflow-x: clip / overflow-x: hidden on body
  • overscroll-behavior-y: none on html/body
  • scroll-behavior: auto instead of smooth on mobile
  • viewport-fit=cover in viewport meta tag
  • min-height: 100dvh / 200vh on content containers

JS approaches:

  • window.visualViewport resize/scroll listeners adjusting bottom or top
  • window.scrollTo(0,1); window.scrollTo(0,0) to force viewport recalculation

Nuxt/Vue approaches:

  • Disabling pageTransition
  • Removing await from useAsyncData (non-blocking)
  • Replacing defineAsyncComponent with eager imports
  • Client-only rendering (definePageMeta({ ssr: false }))
  • Moving all logic into a child component (like working pages do)
  • Wrapping layout in flex container

DOM investigation:

  • Scroll event listener on document (capture) shows scroll target is document — no nested scroll container
  • Safari Web Inspector computed styles for body, html, .tab-bar are identical between working and broken pages
  • No transform, filter, contain, or overflow on any ancestor that could break fixed positioning

Environment

  • iOS latest version, Chrome for iOS
  • Nuxt 3 with SSR
  • Layout: sticky header + scrollable content + fixed bottom tab bar

Working vs broken pages

All pages share the same layout (position: sticky header, position: fixed tab bar). The only difference is the page component content. Even a clone of
the broken page at a different URL reproduces the bug.

Broken pages have useAsyncData fetching content from an API and rendering dynamic blocks. Working pages (/shop, /cart) either have no useAsyncData or
render static component trees. However, /product also uses useAsyncData and works fine.

Replacing dynamic rendering with static components, hardcoded data, or client-only rendering did NOT fix the issue.

Question

What could cause iOS Chrome to render position: fixed and position: sticky elements as if they're scrolling with the page, only on specific pages, and
only on the first load of a session? Is there a known iOS Chrome/WebKit behavior that causes this?

Code:


.tab-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
width: 100%;
max-width: 100%;
z-index: 9;
background-color: $dark;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 1.25rem;
border-top: 1px solid $gray_4;
height: 4.375rem;

Screens:
https://gyazo.com/6f5981a7e2de00063dbe41c506d992f3
https://gyazo.com/8cfa4122dff2990f8721ccdadff770ad

css ios google-chrome nuxt.js position