Skip to content

Commit b36db69

Browse files
committed
Native navigation on iOS: back button and swipe were exiting the site
iOS WebKit's back-trapping heuristic makes the user-facing back button/swipe skip history entries it deems added without user interaction - which covers entries the ClientRouter pushes after its async page fetch. Every in-site navigation got flagged, so one back gesture vaulted past all of them, out of the site. (Programmatic history.back() ignores the heuristic, which is why automated checks passed.) On iOS/iPadOS, internal links are now marked data-astro-reload so the router stands down and navigation stays native - correct history by construction, at the cost of ordinary page loads there. Other platforms keep client-side routing. Refs: whatwg/html#7832, WebKit skip logic per Chromium navigation-dev.
1 parent f6a8878 commit b36db69

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

‎src/layouts/Layout.astro‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,27 @@ const ogImage = new URL('/og-image.png', Astro.site);
5353
<ClientRouter />
5454
</head>
5555
<body class="bg-bg text-white">
56+
<script>
57+
/* iOS WebKit's back-trapping heuristic skips history entries it considers
58+
added without user interaction — which includes entries the ClientRouter
59+
pushes after its async page fetch. Result: back button / swipe-back
60+
jumps clean out of the site. On iOS, mark internal links
61+
data-astro-reload so navigation stays native and history correct;
62+
everyone else keeps client-side routing. */
63+
const isIOS =
64+
/iPhone|iPad|iPod/.test(navigator.userAgent) ||
65+
(navigator.userAgent.includes('Mac') && navigator.maxTouchPoints > 1); /* iPadOS masquerades as macOS */
66+
67+
if (isIOS) {
68+
const optOut = () => {
69+
document.querySelectorAll('a[href^="/"]:not([data-astro-reload])').forEach((a) => {
70+
a.setAttribute('data-astro-reload', '');
71+
});
72+
};
73+
optOut();
74+
document.addEventListener('astro:page-load', optOut);
75+
}
76+
</script>
5677
{countdown && <CountdownBar />}
5778
<FlameBackdrop />
5879
<!-- relative lifts all page content above the absolutely-positioned shader,

0 commit comments

Comments
 (0)