This feature is not Baseline because it does not work in some of the most widely-used browsers.
The PageSwapEvent event object is made available inside handler functions for the pageswap event.
The pageswap event is fired when you navigate across documents, when the previous document is about to unload. During a cross-document navigation, the PageSwapEvent event object allows you to manipulate the related view transition (providing access to the relevant ViewTransition object) from the document being navigated from, if a view transition was triggered by the navigation. It also provides access to information on the navigation type and current and destination documents.
PageSwapEvent()Creates a new PageSwapEvent object instance.
activation Read only
Contains a NavigationActivation object containing the navigation type and current and destination document history entries for a same-origin navigation. If the navigation has a cross-origin URL anywhere in the redirect chain, it returns null.
viewTransition Read only
Contains a ViewTransition object representing the active view transition for the cross-document navigation.
window.addEventListener("pageswap", async (e) => {
// Only run this if an active view transition exists
if (e.viewTransition) {
const currentUrl = e.activation.from?.url
? new URL(e.activation.from.url)
: null;
const targetUrl = new URL(e.activation.entry.url);
// Going from profile page to homepage
// ~> The big img and title are the ones!
if (isProfilePage(currentUrl) && isHomePage(targetUrl)) {
// Set view-transition-name values on the elements to animate
document.querySelector(`#detail main h1`).style.viewTransitionName =
"name";
document.querySelector(`#detail main img`).style.viewTransitionName =
"avatar";
// Remove view-transition-names after snapshots have been taken
// Stops naming conflicts resulting from the page state persisting in BFCache
await e.viewTransition.finished;
document.querySelector(`#detail main h1`).style.viewTransitionName =
"none";
document.querySelector(`#detail main img`).style.viewTransitionName =
"none";
}
// Going to profile page
// ~> The clicked items are the ones!
if (isProfilePage(targetUrl)) {
const profile = extractProfileNameFromUrl(targetUrl);
// Set view-transition-name values on the elements to animate
document.querySelector(`#${profile} span`).style.viewTransitionName =
"name";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"avatar";
// Remove view-transition-names after snapshots have been taken
// Stops naming conflicts resulting from the page state persisting in BFCache
await e.viewTransition.finished;
document.querySelector(`#${profile} span`).style.viewTransitionName =
"none";
document.querySelector(`#${profile} img`).style.viewTransitionName =
"none";
}
}
});
Note: See List of Chrome DevRel team members for the live demo this code is taken from.
| Specification |
|---|
| HTML> # the-pageswapevent-interface> |
| Desktop | Mobile | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | WebView on iOS | |
PageSwapEvent |
128 | 128 | No | 114 | 18.2 | 128 | No | 85 | 18.2 | 28.0 | 128 | 18.2 |
PageSwapEvent |
124 | 124 | No | 110 | 18.2 | 124 | No | 82 | 18.2 | 27.0 | 124 | 18.2 |
activation |
124 | 124 | No | 110 | 18.2 | 124 | No | 82 | 18.2 | 27.0 | 124 | 18.2 |
viewTransition |
126 | 126 | No | 112 | 18.2 | 126 | No | 83 | 18.2 | 28.0 | 126 | 18.2 |
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/PageSwapEvent