Skip to content

Commit b733808

Browse files
committed
docs(nav[spa]): wrap DOM swap in View Transitions API for smooth crossfade
why: SPA navigation instantly replaces DOM content, causing a jarring visual jump between pages instead of a smooth transition. what: - Wrap swap+reinit in document.startViewTransition() when available - Add 150ms crossfade animation via ::view-transition pseudo-elements - Progressive enhancement: unsupported browsers get instant swap
1 parent 7f113a8 commit b733808

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

docs/_static/css/custom.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,16 @@ article {
197197
* sets max-width: 100%; height: auto on img. We add
198198
* content-visibility and badge-specific height to prevent CLS.
199199
* ────────────────────────────────────────────────────────── */
200+
201+
/* ── View Transitions (SPA navigation) ────────────────────
202+
* Crossfade between pages during SPA navigation.
203+
* Browsers without View Transitions API get instant swap.
204+
* ────────────────────────────────────────────────────────── */
205+
::view-transition-old(root),
206+
::view-transition-new(root) {
207+
animation-duration: 150ms;
208+
}
209+
200210
img {
201211
content-visibility: auto;
202212
}

docs/_static/js/spa-nav.js

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -160,21 +160,29 @@
160160
if (!doc.querySelector(".article-container"))
161161
throw new Error("no article");
162162

163-
swap(doc);
163+
var applySwap = function () {
164+
swap(doc);
165+
166+
if (!isPop) history.pushState({ spa: true }, "", url);
167+
168+
if (!isPop) {
169+
var hash = new URL(url, location.href).hash;
170+
if (hash) {
171+
var el = document.querySelector(hash);
172+
if (el) el.scrollIntoView();
173+
} else {
174+
window.scrollTo(0, 0);
175+
}
176+
}
164177

165-
if (!isPop) history.pushState({ spa: true }, "", url);
178+
reinit();
179+
};
166180

167-
if (!isPop) {
168-
var hash = new URL(url, location.href).hash;
169-
if (hash) {
170-
var el = document.querySelector(hash);
171-
if (el) el.scrollIntoView();
172-
} else {
173-
window.scrollTo(0, 0);
174-
}
181+
if (document.startViewTransition) {
182+
document.startViewTransition(applySwap);
183+
} else {
184+
applySwap();
175185
}
176-
177-
reinit();
178186
} catch (err) {
179187
if (err.name === "AbortError") return;
180188
window.location.href = url;

0 commit comments

Comments
 (0)