diff --git a/files/en-us/web/api/document/startviewtransition/index.md b/files/en-us/web/api/document/startviewtransition/index.md index 82e052ae16058fa..49d4f43b8b161d7 100644 --- a/files/en-us/web/api/document/startviewtransition/index.md +++ b/files/en-us/web/api/document/startviewtransition/index.md @@ -10,9 +10,9 @@ browser-compat: api.Document.startViewTransition {{APIRef("View Transitions API")}}{{SeeCompatTable}} -The **`startViewTransition()`** method of the {{domxref("Document")}} interface starts a new view transition and returns a {{domxref("ViewTransition")}} object to represent it. +The **`startViewTransition()`** method of the {{domxref("Document")}} interface starts a new same-document (SPA) [view transition](/en-US/docs/Web/API/View_Transitions_API) and returns a {{domxref("ViewTransition")}} object to represent it. -When `startViewTransition()` is invoked, a sequence of steps is followed as explained in [The view transition process](/en-US/docs/Web/API/View_Transitions_API#the_view_transition_process). +When `startViewTransition()` is invoked, a sequence of steps is followed as explained in [The view transition process](/en-US/docs/Web/API/View_Transitions_API/Using#the_view_transition_process). ## Syntax @@ -24,7 +24,7 @@ startViewTransition(updateCallback) ### Parameters - `updateCallback` {{optional_inline}} - - : An optional callback function typically invoked to update the DOM during the view transition process, which returns a {{jsxref("Promise")}}. The callback is invoked once the API has taken a screenshot of the current page. When the promise returned by the callback fulfills, the view transition begins in the next frame. If the promise returned by the callback rejects, the transition is abandoned. + - : An optional callback function typically invoked to update the DOM during the SPA view transition process, which returns a {{jsxref("Promise")}}. The callback is invoked once the API has taken a snapshot of the current page. When the promise returned by the callback fulfills, the view transition begins in the next frame. If the promise returned by the callback rejects, the transition is abandoned. ### Return value @@ -34,7 +34,7 @@ A {{domxref("ViewTransition")}} object instance. ### Basic usage -In our [Basic View Transitions demo](https://mdn.github.io/dom-examples/view-transitions/), the `updateView()` function handles both browsers that do and don't support the View Transitions API. In supporting browsers, we invoke `startViewTransition()` to set off the view transition process without worrying about the return value. +In our [Basic SPA View Transitions demo](https://mdn.github.io/dom-examples/view-transitions/spa/), the `updateView()` function handles both browsers that do and don't support the View Transitions API. In supporting browsers, we invoke `startViewTransition()` to trigger the view transition process without worrying about the return value. ```js function updateView(event) { diff --git a/files/en-us/web/api/html_dom_api/index.md b/files/en-us/web/api/html_dom_api/index.md index 39a2943c9d02186..0345e3976b80294 100644 --- a/files/en-us/web/api/html_dom_api/index.md +++ b/files/en-us/web/api/html_dom_api/index.md @@ -235,6 +235,8 @@ The History API interfaces let you access information about the browser's histor - {{DOMxRef("HashChangeEvent")}} - {{DOMxRef("History")}} - {{DOMxRef("Location")}} +- {{DOMxRef("PageRevealEvent")}} +- {{DOMxRef("PageSwapEvent")}} - {{DOMxRef("PageTransitionEvent")}} - {{DOMxRef("PopStateEvent")}} diff --git a/files/en-us/web/api/navigation_api/index.md b/files/en-us/web/api/navigation_api/index.md index 3fe25516a83fc62..da09e490ea75c09 100644 --- a/files/en-us/web/api/navigation_api/index.md +++ b/files/en-us/web/api/navigation_api/index.md @@ -90,6 +90,8 @@ There are a few perceived limitations with the Navigation API: - : Event object for the {{domxref("Navigation/navigate_event", "navigate")}} event, which fires when [any type of navigation](https://github.com/WICG/navigation-api#appendix-types-of-navigations) is initiated. It provides access to information about that navigation, and most notably the {{domxref("NavigateEvent.intercept", "intercept()")}}, which allows you to control what happens when the navigation is initiated. - {{domxref("Navigation")}} {{Experimental_Inline}} - : Allows control over all navigation actions for the current `window` in one central place, including initiating navigations programmatically, examining navigation history entries, and managing navigations as they happen. +- {{domxref("NavigationActivation")}} + - : Represents a recent cross-document navigation. It contains the navigation type and current and destination document history entries. - {{domxref("NavigationCurrentEntryChangeEvent")}} {{Experimental_Inline}} - : Event object for the {{domxref("Navigation/currententrychange_event", "currententrychange")}} event, which fires when the {{domxref("Navigation.currentEntry")}} has changed. It provides access to the navigation type, and the previous history entry that was navigated from. - {{domxref("NavigationDestination")}} {{Experimental_Inline}} diff --git a/files/en-us/web/api/navigationactivation/entry/index.md b/files/en-us/web/api/navigationactivation/entry/index.md new file mode 100644 index 000000000000000..09ba309845a24d4 --- /dev/null +++ b/files/en-us/web/api/navigationactivation/entry/index.md @@ -0,0 +1,36 @@ +--- +title: "NavigationActivation: entry property" +short-title: entry +slug: Web/API/NavigationActivation/entry +page-type: web-api-instance-property +status: + - experimental +browser-compat: api.NavigationActivation.entry +--- + +{{APIRef("Navigation API")}}{{SeeCompatTable}} + +The **`entry`** read-only property of the {{domxref("NavigationActivation")}} interface contains a {{domxref("NavigationHistoryEntry")}} object representing the history entry for the inbound ("to") document in the navigation. This is equivalent to the {{domxref("Navigation.currentEntry")}} property at the moment the inbound document was activated. + +There are some cases in which either the from or entry NavigationHistoryEntry objects would not be viable targets for the traverseTo() method, as they might not be retained in history. For example, the Document can be activated using location.replace() or its initial entry could be replaced by history.replaceState(). However, those entries' url property and getState() method are still accessible. + +## Value + +A {{domxref("NavigationHistoryEntry")}} object. + +## Examples + +See the main {{domxref("NavigationActivation")}} page. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Navigation API](/en-US/docs/Web/API/Navigation_API) +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/navigationactivation/from/index.md b/files/en-us/web/api/navigationactivation/from/index.md new file mode 100644 index 000000000000000..682834b202b24de --- /dev/null +++ b/files/en-us/web/api/navigationactivation/from/index.md @@ -0,0 +1,37 @@ +--- +title: "NavigationActivation: from property" +short-title: from +slug: Web/API/NavigationActivation/from +page-type: web-api-instance-property +status: + - experimental +browser-compat: api.NavigationActivation.from +--- + +{{APIRef("Navigation API")}}{{SeeCompatTable}} + +The **`from`** read-only property of the {{domxref("NavigationActivation")}} interface contains a {{domxref("NavigationHistoryEntry")}} object representing the history entry for the outgoing ("from") document in the navigation. + +## Value + +A {{domxref("NavigationHistoryEntry")}} object, or `null` if the outgoing document is: + +- Not same origin as the inbound document. +- The initial `about:blank` document. + +## Examples + +See the main {{domxref("NavigationActivation")}} page. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Navigation API](/en-US/docs/Web/API/Navigation_API) +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/navigationactivation/index.md b/files/en-us/web/api/navigationactivation/index.md new file mode 100644 index 000000000000000..ce6fd9b07073157 --- /dev/null +++ b/files/en-us/web/api/navigationactivation/index.md @@ -0,0 +1,94 @@ +--- +title: NavigationActivation +slug: Web/API/NavigationActivation +page-type: web-api-interface +status: + - experimental +browser-compat: api.NavigationActivation +--- + +{{APIRef("Navigation API")}}{{SeeCompatTable}} + +The **`NavigationActivation`** interface of the [Navigation API](/en-US/docs/Web/API/Navigation_API) represents a recent cross-document navigation. It contains the navigation type and outgoing and inbound document history entries. + +This object is accessed via the {{domxref("PageSwapEvent.activation")}} and {{domxref("Navigation.activation")}} properties. Note that, in each case, the `NavigationActivation` represents a different navigation: + +- `Navigation.activation` represents information about the navigation to the current page. +- `PageSwapEvent.activation` represents information about the navigation to the next page. + +## Instance properties + +- {{domxref("NavigationActivation.entry", "entry")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Contains a {{domxref("NavigationHistoryEntry")}} object representing the history entry for the inbound ("to") document in the navigation. This is equivalent to the {{domxref("Navigation.currentEntry")}} property at the moment the inbound document was activated. +- {{domxref("NavigationActivation.from", "from")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Contains a {{domxref("NavigationHistoryEntry")}} object representing the history entry for the outgoing ("from") document in the navigation. +- {{domxref("NavigationActivation.navigationType", "navigationType")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Contains a string indicating the type of navigation. + +## Examples + +```js +window.addEventListener("pagereveal", async (e) => { + // If the "from" history entry does not exist, return + if (!navigation.activation.from) return; + + // Only run this if an active view transition exists + if (e.viewTransition) { + const fromUrl = new URL(navigation.activation.from.url); + const currentUrl = new URL(navigation.activation.entry.url); + + // Went from profile page to homepage + // ~> Set VT names on the relevant list item + if (isProfilePage(fromUrl) && isHomePage(currentUrl)) { + const profile = extractProfileNameFromUrl(fromUrl); + + // 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 names after snapshots have been taken + // so that we're ready for the next navigation + await e.viewTransition.ready; + document.querySelector(`#${profile} span`).style.viewTransitionName = + "none"; + document.querySelector(`#${profile} img`).style.viewTransitionName = + "none"; + } + + // Went to profile page + // ~> Set VT names on the main title and image + if (isProfilePage(currentUrl)) { + // 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 names after snapshots have been taken + // so that we're ready for the next navigation + await e.viewTransition.ready; + document.querySelector(`#detail main h1`).style.viewTransitionName = + "none"; + document.querySelector(`#detail main img`).style.viewTransitionName = + "none"; + } + } +}); +``` + +> **Note:** See [List of Chrome Dev Rel team members](https://view-transitions.netlify.app/profiles/mpa/) for the live demo this code is taken from. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Navigation API](/en-US/docs/Web/API/Navigation_API) +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/navigationactivation/navigationtype/index.md b/files/en-us/web/api/navigationactivation/navigationtype/index.md new file mode 100644 index 000000000000000..98743993dda7743 --- /dev/null +++ b/files/en-us/web/api/navigationactivation/navigationtype/index.md @@ -0,0 +1,49 @@ +--- +title: "NavigationActivation: navigationType property" +short-title: navigationType +slug: Web/API/NavigationActivation/navigationType +page-type: web-api-instance-property +status: + - experimental +browser-compat: api.NavigationActivation.navigationType +--- + +{{APIRef("Navigation API")}}{{SeeCompatTable}} + +The **`navigationType`** read-only property of the {{domxref("NavigationActivation")}} interface contains a string indicating the type of navigation. + +## Value + +A string representing the type of navigation the {{domxref("NavigationActivation")}} relates to. Possible values are: + +- `push`: A new location was navigated to, causing a new entry to be pushed onto the history list. +- `reload`: The {{domxref("NavigationActivation.entry")}} was reloaded. +- `replace`: The {{domxref("NavigationActivation.entry")}} was replaced with a new history entry. This new entry will reuse the same {{domxref("NavigationHistoryEntry.key", "key")}}, but be assigned a different {{domxref("NavigationHistoryEntry.id", "id")}}. +- `traverse`: The browser navigated from one existing history entry to another existing history entry. + +## Examples + +```js +window.addEventListener("pageswap", (event) => { + // For example, the page was hidden, or the navigation is cross-document. + if (!event.viewTransition) return; + + // Skip the view transition for back/forward navigations. + if (event.activation.navigationType === "traverse") { + event.viewTransition.skipTransition(); + } +}); +``` + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Navigation API](/en-US/docs/Web/API/Navigation_API) +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/pagerevealevent/index.md b/files/en-us/web/api/pagerevealevent/index.md new file mode 100644 index 000000000000000..655646b72508531 --- /dev/null +++ b/files/en-us/web/api/pagerevealevent/index.md @@ -0,0 +1,104 @@ +--- +title: PageRevealEvent +slug: Web/API/PageRevealEvent +page-type: web-api-interface +status: + - experimental +browser-compat: api.PageRevealEvent +--- + +{{APIRef("HTML DOM")}}{{SeeCompatTable}} + +The **`PageRevealEvent`** event object is made available inside handler functions for the {{domxref("Window.pagereveal_event", "pagereveal")}} event. + +During a cross-document navigation, it allows you to manipulate a related [view transition](/en-US/docs/Web/API/View_Transitions_API) (providing access to the relevant {{domxref("ViewTransition")}} object) from the document being navigated _to_, if a view transition was triggered by the navigation. + +Outside view transitions, this event is also useful for cases such as triggering a startup animation, or reporting a page view. It's equivalent to the first {{domxref("Window.requestAnimationFrame()")}} run after a cross-document navigation, if you were to trigger `requestAnimationFrame()` in the {{htmlelement("head")}} of the document. For example, if you ran the following `reveal()` function in the ``: + +```js +function reveal() { + // Include startup animation here +} +/* This will fire in the first rendered frame after loading */ +requestAnimationFrame(() => reveal()); + +/* This will fire if the page is restored from BFCache */ +window.onpagehide = () => requestAnimationFrame(() => reveal()); +``` + +## Constructor + +- {{domxref("PageRevealEvent.PageRevealEvent", "PageRevealEvent()")}} + - : Creates a new {{domxref("PageRevealEvent")}} object instance. + +## Instance properties + +- {{domxref("PageRevealEvent.viewTransition", "viewTransition")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Contains a {{domxref("ViewTransition")}} object representing the active view transition for the cross-document navigation. + +## Examples + +```js +window.addEventListener("pagereveal", async (e) => { + // If the "from" history entry does not exist, return + if (!navigation.activation.from) return; + + // Only run this if an active view transition exists + if (e.viewTransition) { + const fromUrl = new URL(navigation.activation.from.url); + const currentUrl = new URL(navigation.activation.entry.url); + + // Went from profile page to homepage + // ~> Set VT names on the relevant list item + if (isProfilePage(fromUrl) && isHomePage(currentUrl)) { + const profile = extractProfileNameFromUrl(fromUrl); + + // 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 names after snapshots have been taken + // so that we're ready for the next navigation + await e.viewTransition.ready; + document.querySelector(`#${profile} span`).style.viewTransitionName = + "none"; + document.querySelector(`#${profile} img`).style.viewTransitionName = + "none"; + } + + // Went to profile page + // ~> Set VT names on the main title and image + if (isProfilePage(currentUrl)) { + // 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 names after snapshots have been taken + // so that we're ready for the next navigation + await e.viewTransition.ready; + document.querySelector(`#detail main h1`).style.viewTransitionName = + "none"; + document.querySelector(`#detail main img`).style.viewTransitionName = + "none"; + } + } +}); +``` + +> **Note:** See [List of Chrome Dev Rel team members](https://view-transitions.netlify.app/profiles/mpa/) for the live demo this code is taken from. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/pagerevealevent/pagerevealevent/index.md b/files/en-us/web/api/pagerevealevent/pagerevealevent/index.md new file mode 100644 index 000000000000000..3b87cbb0858abcc --- /dev/null +++ b/files/en-us/web/api/pagerevealevent/pagerevealevent/index.md @@ -0,0 +1,45 @@ +--- +title: "PageRevealEvent: PageRevealEvent() constructor" +short-title: PageRevealEvent() +slug: Web/API/PageRevealEvent/PageRevealEvent +page-type: web-api-constructor +status: + - experimental +browser-compat: api.PageRevealEvent.PageRevealEvent +--- + +{{APIRef("HTML DOM")}}{{SeeCompatTable}} + +The **`PageRevealEvent()`** constructor creates a new +{{domxref("PageRevealEvent")}} object instance. + +## Syntax + +```js-nolint +new PageRevealEvent(type, init) +``` + +### Parameters + +- `type` + - : A string representing the type of event. In the case of `PageRevealEvent` this is always `pagereveal`. +- `init` + - : An object containing the following properties: + - `viewTransition` {{optional_inline}} + - : A {{domxref("ViewTransition")}} object representing the active view transition for the related navigation. Defaults to `null` if there is no active view transition. + +## Examples + +A developer would not use this constructor manually. A new `PageRevealEvent` object is constructed when a handler is invoked as a result of the {{domxref("Window.pagereveal_event", "pagereveal")}} event firing. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/pagerevealevent/viewtransition/index.md b/files/en-us/web/api/pagerevealevent/viewtransition/index.md new file mode 100644 index 000000000000000..c8ae71d6b4b284a --- /dev/null +++ b/files/en-us/web/api/pagerevealevent/viewtransition/index.md @@ -0,0 +1,34 @@ +--- +title: "PageRevealEvent: viewTransition property" +short-title: viewTransition +slug: Web/API/PageRevealEvent/viewTransition +page-type: web-api-instance-property +status: + - experimental +browser-compat: api.PageRevealEvent.viewTransition +--- + +{{APIRef("HTML DOM")}}{{SeeCompatTable}} + +The **`viewTransition`** read-only property of the {{domxref("PageRevealEvent")}} interface contains a {{domxref("ViewTransition")}} object representing the active view transition for the cross-document navigation. + +## Value + +A {{domxref("ViewTransition")}} object, or `null` if no view transition is active when the event is fired. + +## Examples + +See the main {{domxref("PageRevealEvent")}} page. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Navigation API](/en-US/docs/Web/API/Navigation_API) +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/pageswapevent/activation/index.md b/files/en-us/web/api/pageswapevent/activation/index.md new file mode 100644 index 000000000000000..ad5231f67d895dd --- /dev/null +++ b/files/en-us/web/api/pageswapevent/activation/index.md @@ -0,0 +1,33 @@ +--- +title: "PageSwapEvent: activation property" +short-title: activation +slug: Web/API/PageSwapEvent/activation +page-type: web-api-instance-property +status: + - experimental +browser-compat: api.PageSwapEvent.activation +--- + +{{APIRef("HTML DOM")}}{{SeeCompatTable}} + +The **`activation`** read-only property of the {{domxref("PageSwapEvent")}} interface contains a {{domxref("NavigationActivation")}} object containing the navigation type and current and destination document history entries for a same-origin navigation. + +## Value + +A {{domxref("NavigationActivation")}} object, or `null` if the associated navigation has a cross-origin URL anywhere in the redirect chain. + +## Examples + +See the main {{domxref("PageSwapEvent")}} page. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/pageswapevent/index.md b/files/en-us/web/api/pageswapevent/index.md new file mode 100644 index 000000000000000..1a2b48ae6a52cfb --- /dev/null +++ b/files/en-us/web/api/pageswapevent/index.md @@ -0,0 +1,92 @@ +--- +title: PageSwapEvent +slug: Web/API/PageSwapEvent +page-type: web-api-interface +status: + - experimental +browser-compat: api.PageSwapEvent +--- + +{{APIRef("HTML DOM")}}{{SeeCompatTable}} + +The **`PageSwapEvent`** event object is made available inside handler functions for the {{domxref("Window.pageswap_event", "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](/en-US/docs/Web/API/View_Transitions_API) (providing access to the relevant {{domxref("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. + +## Constructor + +- {{domxref("PageSwapEvent.PageSwapEvent", "PageSwapEvent()")}} + - : Creates a new {{domxref("PageSwapEvent")}} object instance. + +## Instance properties + +- {{domxref("PageSwapEvent.activation", "activation")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Contains a {{domxref("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`. +- {{domxref("PageSwapEvent.viewTransition", "viewTransition")}} {{ReadOnlyInline}} {{Experimental_Inline}} + - : Contains a {{domxref("ViewTransition")}} object representing the active view transition for the cross-document navigation. + +## Examples + +```js +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 Dev Rel team members](https://view-transitions.netlify.app/profiles/mpa/) for the live demo this code is taken from. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/pageswapevent/pageswapevent/index.md b/files/en-us/web/api/pageswapevent/pageswapevent/index.md new file mode 100644 index 000000000000000..e5336b3a418f2cf --- /dev/null +++ b/files/en-us/web/api/pageswapevent/pageswapevent/index.md @@ -0,0 +1,47 @@ +--- +title: "PageSwapEvent: PageSwapEvent() constructor" +short-title: PageSwapEvent() +slug: Web/API/PageSwapEvent/PageSwapEvent +page-type: web-api-constructor +status: + - experimental +browser-compat: api.PageSwapEvent.PageSwapEvent +--- + +{{APIRef("HTML DOM")}}{{SeeCompatTable}} + +The **`PageSwapEvent()`** constructor creates a new +{{domxref("PageSwapEvent")}} object instance. + +## Syntax + +```js-nolint +new PageSwapEvent(type, init) +``` + +### Parameters + +- `type` + - : A string representing the type of event. In the case of `PageSwapEvent` this is always `pageswap`. +- `init` + - : An object containing the following properties: + - `activation` + - : A {{domxref("NavigationActivation")}} object representing the navigation type and current and destination document history entries. Defaults to `null` if the associated navigation is a cross-origin navigation. + - `viewTransition` + - : A {{domxref("ViewTransition")}} object representing the active view transition for the related navigation. Defaults to `null` if there is no active view transition. + +## Examples + +A developer would not use this constructor manually. A new `PageSwapEvent` object is constructed when a handler is invoked as a result of the {{domxref("Window.pageswap_event", "pageswap")}} event firing. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/pageswapevent/viewtransition/index.md b/files/en-us/web/api/pageswapevent/viewtransition/index.md new file mode 100644 index 000000000000000..350a758553abaf7 --- /dev/null +++ b/files/en-us/web/api/pageswapevent/viewtransition/index.md @@ -0,0 +1,33 @@ +--- +title: "PageSwapEvent: viewTransition property" +short-title: viewTransition +slug: Web/API/PageSwapEvent/viewTransition +page-type: web-api-instance-property +status: + - experimental +browser-compat: api.PageSwapEvent.viewTransition +--- + +{{APIRef("HTML DOM")}}{{SeeCompatTable}} + +The **`viewTransition`** read-only property of the {{domxref("PageRevealEvent")}} interface contains a {{domxref("ViewTransition")}} object representing the active view transition for the cross-document navigation. + +## Value + +A {{domxref("ViewTransition")}} object, or `null` if no view transition is active when the event is fired. + +## Examples + +See the main {{domxref("PageSwapEvent")}} page. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/api/view_transitions_api/index.md b/files/en-us/web/api/view_transitions_api/index.md index 04d3fd0ef96b315..881bc23db331a11 100644 --- a/files/en-us/web/api/view_transitions_api/index.md +++ b/files/en-us/web/api/view_transitions_api/index.md @@ -6,265 +6,33 @@ status: - experimental browser-compat: - api.Document.startViewTransition - - api.ViewTransition + - css.at-rules.view-transition spec-urls: https://drafts.csswg.org/css-view-transitions/ --- {{SeeCompatTable}}{{DefaultAPISidebar("View Transitions API")}} -The **View Transitions API** provides a mechanism for easily creating animated transitions between different DOM states while also updating the DOM contents in a single step. +The **View Transitions API** provides a mechanism for easily creating animated transitions between different website views. This includes animating between DOM states in a single-page app (SPA), and animating the navigation between documents in a multi-page app (MPA). ## Concepts and usage View transitions are a popular design choice for reducing users' cognitive load, helping them stay in context, and reducing perceived loading latency as they move between states or views of an application. -However, creating view transitions on the web has historically been difficult. Transitions between states in single-page apps (SPAs) tend to involve writing significant CSS and JavaScript to: +However, creating view transitions on the web has historically been difficult: -- Handle the loading and positioning of the old and new content. -- Animate the old and new states to create the transition. -- Stop accidental user interactions with the old content from causing problems. -- Remove the old content once the transition is complete. +- Transitions between states in single-page apps (SPAs) tend to involve writing significant CSS and JavaScript to: + - Handle the loading and positioning of the old and new content. + - Animate the old and new states to create the transition. + - Stop accidental user interactions with the old content from causing problems. + - Remove the old content once the transition is complete. + Accessibility issues like loss of reading position, focus confusion, and strange live region announcement behavior can also result from having the new and old content both present in the DOM at once. +- Cross-document view transitions (i.e. across navigations between different pages in MPAs) have historically been impossible. -Accessibility issues like loss of reading position, focus confusion, and strange live region announcement behavior can also result from having the new and old content both present in the DOM at once. In addition, cross-document view transitions (i.e. across different pages in regular, non-SPA websites) are impossible. +The View Transitions API provides an easy way of handling the required view changes and transition animations for both the above use cases. -The View Transitions API provides a much easier way of handling the required DOM changes and transition animations. +Creating a view transition that uses the browser's default transition animations is very quick to do, and there are features that allow you to both customize the transition animation and manipulate the view transition itself (for example specify circumstances under which the animation is skipped), for both SPA and MPA view transitions. -> **Note:** The View Transitions API doesn't currently enable cross-document view transitions, but this is planned for a future level of the spec and is actively being worked on. - -### Creating a basic view transition - -As an example, an SPA may include functionality to fetch new content and update the DOM in response to an event of some kind, such as a navigation link being clicked or an update being pushed from the server. In our [Basic View Transitions demo](https://mdn.github.io/dom-examples/view-transitions/) we've simplified this to a `displayNewImage()` function that shows a new full-size image based on the thumbnail that was clicked. We've encapsulated this inside an `updateView()` function that only calls the View Transition API if the browser supports it: - -```js -function updateView(event) { - // Handle the difference in whether the event is fired on the or the - const targetIdentifier = event.target.firstChild || event.target; - - const displayNewImage = () => { - const mainSrc = `${targetIdentifier.src.split("_th.jpg")[0]}.jpg`; - galleryImg.src = mainSrc; - galleryCaption.textContent = targetIdentifier.alt; - }; - - // Fallback for browsers that don't support View Transitions: - if (!document.startViewTransition) { - displayNewImage(); - return; - } - - // With View Transitions: - const transition = document.startViewTransition(() => displayNewImage()); -} -``` - -This code is enough to handle the transition between displayed images. Supporting browsers will show the change from old to new images and captions as a smooth cross-fade (the default view transition). It will still work in non-supporting browsers but without the nice animation. - -It is also worth mentioning that `startViewTransition()` returns a {{domxref("ViewTransition")}} instance, which includes several promises, allowing you to run code in response to different parts of the view transition process being reached. - -### The view transition process - -Let's walk through how this works: - -1. When {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} is called, the API takes a screenshot of the current page. -2. Next, the callback passed to `startViewTransition()` is invoked, in this case `displayNewImage`, which causes the DOM to change. - - When the callback has run successfully, the {{domxref("ViewTransition.updateCallbackDone")}} promise fulfills, allowing you to respond to the DOM updating. - -3. The API captures the new state of the page as a live representation. -4. The API constructs a pseudo-element tree with the following structure: - - ```plain - ::view-transition - └─ ::view-transition-group(root) - └─ ::view-transition-image-pair(root) - ├─ ::view-transition-old(root) - └─ ::view-transition-new(root) - ``` - - - {{cssxref("::view-transition")}} is the root of view transitions overlay, which contains all view transitions and sits over the top of all other page content. - - {{cssxref("::view-transition-old")}} is the screenshot of the old page view, and {{cssxref("::view-transition-new")}} is the live representation of the new page view. Both of these render as replaced content, in the same manner as an {{htmlelement("img")}} or {{htmlelement("video")}}, meaning that they can be styled with handy properties like {{cssxref("object-fit")}} and {{cssxref("object-position")}}. - - When the transition animation is about to run, the {{domxref("ViewTransition.ready")}} promise fulfills, allowing you to respond by running a custom JavaScript animation instead of the default, for example. - -5. The old page view animates from {{cssxref("opacity")}} 1 to 0, while the new view animates from `opacity` 0 to 1, which is what creates the default cross-fade. -6. When the transition animation has reached its end state, the {{domxref("ViewTransition.finished")}} promise fulfills, allowing you to respond. - -> **Note:** -> If the document's [page visibility state](/en-US/docs/Web/API/Page_Visibility_API) is `hidden` (for example if the document is obscured by a window, the browser is minimized, or another browser tab is active) during a {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} call, the view transition is skipped entirely. - -### Different transitions for different elements - -At the moment, all of the different elements that change when the DOM updates are transitioned using the same animation. If you want different elements to animate differently from the default "root" animation, you can separate them out using the {{cssxref("view-transition-name")}} property. For example: - -```css -figcaption { - view-transition-name: figure-caption; -} -``` - -We've given the {{htmlelement("figcaption")}} element a `view-transition-name` of `figure-caption` to separate it from the rest of the page in terms of view transitions. - -With this CSS applied, the pseudo-element tree will now look like this: - -```plain -::view-transition -├─ ::view-transition-group(root) -│ └─ ::view-transition-image-pair(root) -│ ├─ ::view-transition-old(root) -│ └─ ::view-transition-new(root) -└─ ::view-transition-group(figure-caption) - └─ ::view-transition-image-pair(figure-caption) - ├─ ::view-transition-old(figure-caption) - └─ ::view-transition-new(figure-caption) -``` - -The existence of the second set of pseudo-elements allows separate view transition styling to be applied just to the `
`. The different old and new page view captures are handled completely separate from one another. - -The value of `view-transition-name` can be anything you want except for `none` — the `none` value specifically means that the element will not participate in a view transition. - -> **Note:** `view-transition-name` must be unique. If two rendered elements have the same `view-transition-name` at the same time, {{domxref("ViewTransition.ready")}} will reject and the transition will be skipped. - -### Customizing your animations - -The View Transitions pseudo-elements have default [CSS Animations](/en-US/docs/Web/CSS/CSS_animations) applied (which are detailed in their [reference pages](#css_additions)). - -Notably, transitions for `height`, `width`, `position`, and `transform` do not use the smooth cross-fade animation. Instead, height and width transitions apply a smooth scaling animation. Meanwhile, position and transform transitions apply smooth movement animations to the element. - -You can modify the default animation in any way you want using regular CSS. - -For example, to change the speed of it: - -```css -::view-transition-old(root), -::view-transition-new(root) { - animation-duration: 0.5s; -} -``` - -Let's look at something more interesting — a custom animation for the `
`: - -```css -@keyframes grow-x { - from { - transform: scaleX(0); - } - to { - transform: scaleX(1); - } -} - -@keyframes shrink-x { - from { - transform: scaleX(1); - } - to { - transform: scaleX(0); - } -} - -::view-transition-old(figure-caption), -::view-transition-new(figure-caption) { - height: auto; - right: 0; - left: auto; - transform-origin: right center; -} - -::view-transition-old(figure-caption) { - animation: 0.25s linear both shrink-x; -} - -::view-transition-new(figure-caption) { - animation: 0.25s 0.25s linear both grow-x; -} -``` - -Here we've created a custom CSS animation and applied it to the `::view-transition-old(figure-caption)` and `::view-transition-new(figure-caption)` pseudo-elements. We've also added a number of other styles to both to keep them in the same place and stop the default styling from interfering with our custom animations. - -Note that we also discovered another transition option that is simpler and produced a nicer result than the above. Our final `
` view transition ended up looking like this: - -```css -figcaption { - view-transition-name: figure-caption; -} - -::view-transition-old(figure-caption), -::view-transition-new(figure-caption) { - height: 100%; -} -``` - -This works because, by default, `::view-transition-group` transitions width and height between the old and new views. We just needed to set a fixed `height` on both states to make it work. - -> **Note:** [Smooth and simple transitions with the View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/) contains several other customization examples. - -### Controlling animations with JavaScript - -The {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} method returns a {{domxref("ViewTransition")}} object instance, which contains several promise members allowing you to run JavaScript in response to different states of the transition being reached. For example, {{domxref("ViewTransition.ready")}} fulfills once the pseudo-element tree is created and the animation is about to start, whereas {{domxref("ViewTransition.finished")}} fulfills once the animation is finished, and the new page view is visible and interactive to the user. - -For example, the following JavaScript could be used to create a circular reveal view transition emanating from the position of the user's cursor on click, with animation provided by the {{domxref("Web Animations API", "Web Animations API", "", "nocode")}}. - -```js -// Store the last click event -let lastClick; -addEventListener("click", (event) => (lastClick = event)); - -function spaNavigate(data) { - // Fallback for browsers that don’t support this API: - if (!document.startViewTransition) { - updateTheDOMSomehow(data); - return; - } - - // Get the click position, or fallback to the middle of the screen - const x = lastClick?.clientX ?? innerWidth / 2; - const y = lastClick?.clientY ?? innerHeight / 2; - // Get the distance to the furthest corner - const endRadius = Math.hypot( - Math.max(x, innerWidth - x), - Math.max(y, innerHeight - y), - ); - - // Create a transition: - const transition = document.startViewTransition(() => { - updateTheDOMSomehow(data); - }); - - // Wait for the pseudo-elements to be created: - transition.ready.then(() => { - // Animate the root’s new view - document.documentElement.animate( - { - clipPath: [ - `circle(0 at ${x}px ${y}px)`, - `circle(${endRadius}px at ${x}px ${y}px)`, - ], - }, - { - duration: 500, - easing: "ease-in", - // Specify which pseudo-element to animate - pseudoElement: "::view-transition-new(root)", - }, - ); - }); -} -``` - -This animation also requires the following CSS, to turn off the default CSS animation and stop the old and new view states from blending in any way (the new state "wipes" right over the top of the old state, rather than transitioning in): - -```css -::view-transition-image-pair(root) { - isolation: auto; -} - -::view-transition-old(root), -::view-transition-new(root) { - animation: none; - mix-blend-mode: normal; - display: block; -} -``` +See [Using the View Transitions API](/en-US/docs/Web/API/View_Transitions_API/Using) for more information. ## Interfaces @@ -274,10 +42,28 @@ This animation also requires the following CSS, to turn off the default CSS anim ## Extensions to other interfaces - {{domxref("Document.startViewTransition()")}} - - : Starts a new view transition and returns a {{domxref("ViewTransition")}} object to represent it. + - : Starts a new same-document (SPA) view transition and returns a {{domxref("ViewTransition")}} object to represent it. +- {{domxref("PageRevealEvent")}} + - : The event object for the {{domxref("Window.pagereveal_event", "pagereveal")}} event. During a cross-document navigation, it allows you to manipulate the related view transition (providing access to the relevant {{domxref("ViewTransition")}} object) from the document being navigated _to_, if a view transition was triggered by the navigation. +- {{domxref("PageSwapEvent")}} + - : The event object for the {{domxref("Window.pageswap_event", "pageswap")}} event. During a cross-document navigation, it allows you to manipulate the related view transition (providing access to the relevant {{domxref("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 document history entries. +- The {{domxref("Window")}} {{domxref("Window.pagereveal_event", "pagereveal")}} event + - : Fired when a document is first rendered, either when loading a fresh document from the network or activating a document (either from [bfcache](https://web.dev/articles/bfcache) or [prerender](/en-US/docs/Glossary/Prerender)). +- The {{domxref("Window")}} {{domxref("Window.pageswap_event", "pageswap")}} event + - : Fired when a document is about to be unloaded due to a navigation. + +## HTML additions + +- [``](/en-US/docs/Web/HTML/Attributes/rel#expect) + - : Identifies the most critical content in the associated document for the user's initial view of the page. Document rendering will be blocked until the critical content has been parsed, ensuring a consistent first paint — and therefore, view transition — across all supporting browsers. ## CSS additions +### At-rules + +- {{cssxref("@view-transition")}} + - : In the case of a cross-document navigation, `@view-transition` is used to opt in the current and destination documents to undergo a view transition. + ### Properties - {{cssxref("view-transition-name")}} @@ -292,14 +78,16 @@ This animation also requires the following CSS, to turn off the default CSS anim - {{cssxref("::view-transition-image-pair", "::view-transition-image-pair()")}} - : The container for a view transition's old and new views — before and after the transition. - {{cssxref("::view-transition-old", "::view-transition-old()")}} - - : A static screenshot of the old view, before the transition. + - : A static snapshot of the old view, before the transition. - {{cssxref("::view-transition-new", "::view-transition-new()")}} - : A live representation of the new view, after the transition. ## Examples -- [Basic View Transitions demo](https://mdn.github.io/dom-examples/view-transitions/): A basic image gallery demo with separate transitions between old and new images, and old and new captions. -- [HTTP 203 playlist](https://http203-playlist.netlify.app/): A more sophisticated video player demo app that features a number of different view transitions, many of which are explained in [Smooth and simple transitions with the View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/). +- [Basic View Transitions SPA demo](https://mdn.github.io/dom-examples/view-transitions/spa/): A basic image gallery demo with view transitions, featuring separate animations between old and new images, and old and new captions. +- [Basic View Transitions MPA demo](https://mdn.github.io/dom-examples/view-transitions/mpa/): A sample two-page site that demonstrates usage of cross-document (MPA) view transitions, providing a custom "swipe up" transition when the two pages are navigated between. +- [HTTP 203 playlist](https://http203-playlist.netlify.app/): A video player demo app that features several different SPA view transitions, many of which are explained in [Smooth and simple transitions with the View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/). +- [List of Chrome Dev Rel team members](https://view-transitions.netlify.app/profiles/mpa/): A basic team profile pages app that demonstrates how to use the {{domxref("Window.pagereveal_event", "pagereveal")}} and {{domxref("Window.pageswap_event", "pageswap")}} events to customize the outgoing and inbound animations of a cross-document view transition based on the "from" and "to" URLs. ## Specifications diff --git a/files/en-us/web/api/view_transitions_api/using/index.md b/files/en-us/web/api/view_transitions_api/using/index.md new file mode 100644 index 000000000000000..3c8d5f43cffba37 --- /dev/null +++ b/files/en-us/web/api/view_transitions_api/using/index.md @@ -0,0 +1,536 @@ +--- +title: Using the View Transitions API +slug: Web/API/View_Transitions_API/Using +page-type: guide +status: + - experimental +--- + +{{DefaultAPISidebar("View Transitions API")}} + +This article explains the theory behind how the [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) works, how to create view transitions and customize the transition animations, and how to manipulate active view transitions. This covers view transitions for both DOM state updates in a single-page app (SPA), and navigating between documents in a multi-page app (MPA). + +## The view transition process + +Let's walk through the process by which a view transition works: + +1. A view transition is triggered. How this is done depends on the type of view transition: + - In the case of same-document transitions (SPAs), a view transition is triggered by passing the function that would trigger the view change DOM update as a callback to the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} method. + - In the case of cross-document transitions (MPAs), a view transition is triggered by initiating navigation to a new document. Both the current and destination documents of the navigation need to be on the same origin, and opt-in to the view transition by including a {{cssxref("@view-transition")}} at rule in their CSS with a `navigation` descriptor of `auto`. + > **Note:** An active view transition has an associated {{domxref("ViewTransition")}} instance (for example, returned by `startViewTransition()` in the case of same-document (SPA) transitions). The `ViewTransition` object includes several promises, allowing you to run code in response to different parts of the view transition process being reached. See [Controlling view transitions with JavaScript](#controlling_view_transitions_with_javascript) for more information. +2. On the current (old page) view, the API captures snapshots of elements that have a {{cssxref("view-transition-name")}} declared on them. +3. The view change occurs: + + - In the case of same-document transitions (SPAs), the callback passed to `startViewTransition()` is invoked, which causes the DOM to change. + + When the callback has run successfully, the {{domxref("ViewTransition.updateCallbackDone")}} promise fulfills, allowing you to respond to the DOM updating. + + - In the case of cross-document transitions (MPAs), the navigation occurs between the current and destination documents. + +4. The API captures snapshots from the new view as a live representation. + + At this point, the view transition is about to run, and the {{domxref("ViewTransition.ready")}} promise fulfills, allowing you to respond by running a custom JavaScript animation instead of the default, for example. + +5. The old page snapshots animate "out", while the new view snapshots animate "in". By default, the old view snapshots animate from {{cssxref("opacity")}} 1 to 0, and the new view snapshots animate from `opacity` 0 to 1, which creates a cross-fade. +6. When the transition animations have reached their end states, the {{domxref("ViewTransition.finished")}} promise fulfills, allowing you to respond. + +> **Note:** +> If the document's [page visibility state](/en-US/docs/Web/API/Page_Visibility_API) is `hidden` (for example if the document is obscured by a window, the browser is minimized, or another browser tab is active) during a {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} call, the view transition is skipped entirely. + +### The view transition pseudo-element tree + +To handle creating the outbound and inbound transition animations, the API constructs a pseudo-element tree with the following structure: + +```plain +::view-transition +└─ ::view-transition-group(root) + └─ ::view-transition-image-pair(root) + ├─ ::view-transition-old(root) + └─ ::view-transition-new(root) +``` + +> **Note:** a {{cssxref("::view-transition-group")}} subtree is created for every captured `view-transition-name`. + +In the case of same-document transitions (SPAs), the pseudo-element tree is made available in the document. In the case of cross-document transitions (MPAs), the pseudo-element tree is made available in the destination document only. + +The most interesting parts of the tree structure are as follows: + +- {{cssxref("::view-transition")}} is the root of view transitions overlay, which contains all view transition snapshot groups and sits over the top of all other page content. +- A {{cssxref("::view-transition-group")}} acts as a container for each view transition snapshot group. The `root` argument specifies the default snapshot group — the view transition animation will apply to the snapshot whose `view-transition-name` is `root`. By default, this is the {{cssxref(":root")}} element, because the default browser styles define this: + + ```css + :root { + view-transition-name: root; + } + ``` + + Be aware however that page authors can change this by unsetting the above, and setting `view-transition-name: root` on a different element. + +- {{cssxref("::view-transition-old")}} targets the static snapshot of the old page element, and {{cssxref("::view-transition-new")}} targets the live snapshot of the new page element. Both of these render as replaced content, in the same manner as an {{htmlelement("img")}} or {{htmlelement("video")}}, meaning that they can be styled with handy properties like {{cssxref("object-fit")}} and {{cssxref("object-position")}}. + +> **Note:** It is possible to target different DOM elements with different custom view transition animations by setting a different {{cssxref("view-transition-name")}} on each one. In such cases, a `::view-transition-group` is created for each one. See [Different animations for different elements](#different_animations_for_different_elements) for an example. + +> **Note:** As you'll see later, to customize the outbound and inbound animations you need to target the {{cssxref("::view-transition-old")}} and {{cssxref("::view-transition-new")}} pseudo-elements with your animations, respectively. + +## Creating a basic view transition + +This section illustates how to create a basic view transition, in both the SPA and MPA case. + +### Basic SPA view transition + +As an example, an SPA may include functionality to fetch new content and update the DOM in response to an event of some kind, such as a navigation link being clicked or an update being pushed from the server. In our [View Transitions SPA demo](https://mdn.github.io/dom-examples/view-transitions/spa/) we've simplified this to a `displayNewImage()` function that shows a new full-size image based on the thumbnail that was clicked. We've encapsulated this inside an `updateView()` function that only calls the View Transition API if the browser supports it: + +```js +function updateView(event) { + // Handle the difference in whether the event is fired on the or the + const targetIdentifier = event.target.firstChild || event.target; + + const displayNewImage = () => { + const mainSrc = `${targetIdentifier.src.split("_th.jpg")[0]}.jpg`; + galleryImg.src = mainSrc; + galleryCaption.textContent = targetIdentifier.alt; + }; + + // Fallback for browsers that don't support View Transitions: + if (!document.startViewTransition) { + displayNewImage(); + return; + } + + // With View Transitions: + const transition = document.startViewTransition(() => displayNewImage()); +} +``` + +This code is enough to handle the transition between displayed images. Supporting browsers will show the change from old to new images and captions as a smooth cross-fade (the default view transition). It will still work in non-supporting browsers but without the nice animation. + +### Basic MPA view transition + +When creating a cross-document (MPA) view transition, the process is even simpler than for SPAs. No JavaScript is required, as the view update is triggered by a cross-document, same-origin navigation rather than a JavaScript-initiated DOM change. To enable a basic MPA view transition, you need to specify a {{cssxref("@view-transition")}} at-rule in the CSS for both the current and destination documents to opt them in, like so: + +```css +@view-transition { + navigation: auto; +} +``` + +Our [View Transitions MPA demo](https://mdn.github.io/dom-examples/view-transitions/mpa/) shows this at-rule in action, and additionally demonstrates how to [customize the outbound and inbound animations](#customizing_your_animations) of the view transition. + +> **Note:** Currently MPA view transitions can only be created between same-origin documents, but this restriction may be relaxed in future implementations. + +## Customizing your animations + +The View Transitions pseudo-elements have default [CSS Animations](/en-US/docs/Web/CSS/CSS_animations) applied (which are detailed in their [reference pages](/en-US/docs/Web/API/View_Transitions_API#pseudo-elements)). + +Most appearance transitions are given a default smooth cross-fade animation, as mentioned above. There are some exceptions: + +- `height` and `width` transitions have a smooth scaling animation applied. +- `position` and `transform` transitions have a smooth movement animation applied. + +You can modify the default animations in any way you want using regular CSS — target the "from" animation with {{cssxref("::view-transition-old")}}, and the "to" animation with {{cssxref("::view-transition-new")}}. + +For example, to change the speed of both: + +```css +::view-transition-old(root), +::view-transition-new(root) { + animation-duration: 0.5s; +} +``` + +It is recommended that you target the `::view-transition-group()` with such styles in cases where you want to apply them to `::view-transition-old()` and `::view-transition-new()`. Because of the pseudo-element hierarchy and default user-agent styling, the styles will be inherited by both. For example: + +```css +::view-transition-group(root) { + animation-duration: 0.5s; +} +``` + +> **Note:** This is also a good option for safeguarding your code — `::view-transition-group()` also animates and you could end up with different durations for the `group`/`image-pair` pseudo-elements versus the `old` and `new` pseudo-elements. + +In the case of cross-document (MPA) transitions, the pseudo-elements need to be included in the destination document only for the view transition to work. If you want to use the view transition in both directions, you'll need to include it in both, of course. + +Our [View Transitions MPA demo](https://mdn.github.io/dom-examples/view-transitions/mpa/) includes the above CSS, but takes the customization a step further, defining custom animations and applying them to the `::view-transition-old(root)` and `::view-transition-new(root)` pseudo-elements. The result is that the default cross-fade transition is swapped out for a "swipe up" transition when navigation occurs: + +```css +/* Create a custom animation */ + +@keyframes move-out { + from { + transform: translateY(0%); + } + + to { + transform: translateY(-100%); + } +} + +@keyframes move-in { + from { + transform: translateY(100%); + } + + to { + transform: translateY(0%); + } +} + +/* Apply the custom animation to the old and new page states */ + +::view-transition-old(root) { + animation: 0.4s ease-in both move-out; +} + +::view-transition-new(root) { + animation: 0.4s ease-in both move-in; +} +``` + +## Different animations for different elements + +By default, all of the different elements that change during the view update are transitioned using the same animation. If you want some elements to animate differently from the default `root` animation, you can separate them out using the {{cssxref("view-transition-name")}} property. For example, in our [View Transitions SPA demo](https://mdn.github.io/dom-examples/view-transitions/spa/) the {{htmlelement("figcaption")}} elements are given a `view-transition-name` of `figure-caption` to separate them from the rest of the page in terms of view transitions: + +```css +figcaption { + view-transition-name: figure-caption; +} +``` + +With this CSS applied, the generated pseudo-element tree will now look like this: + +```plain +::view-transition +├─ ::view-transition-group(root) +│ └─ ::view-transition-image-pair(root) +│ ├─ ::view-transition-old(root) +│ └─ ::view-transition-new(root) +└─ ::view-transition-group(figure-caption) + └─ ::view-transition-image-pair(figure-caption) + ├─ ::view-transition-old(figure-caption) + └─ ::view-transition-new(figure-caption) +``` + +The existence of the second set of pseudo-elements allows separate view transition styling to be applied just to the `
`. The different old and new view captures are handled separately from one another. + +> **Note:** The value of `view-transition-name` can be anything you want except for `none` — the `none` value specifically means that the element will not participate in a view transition. +> +> `view-transition-name` values must also be unique. If two rendered elements have the same `view-transition-name` at the same time, {{domxref("ViewTransition.ready")}} will reject and the transition will be skipped. + +The following code applies a custom animation just to the `
`: + +```css +@keyframes grow-x { + from { + transform: scaleX(0); + } + to { + transform: scaleX(1); + } +} + +@keyframes shrink-x { + from { + transform: scaleX(1); + } + to { + transform: scaleX(0); + } +} + +::view-transition-group(figure-caption) { + height: auto; + right: 0; + left: auto; + transform-origin: right center; +} + +::view-transition-old(figure-caption) { + animation: 0.25s linear both shrink-x; +} + +::view-transition-new(figure-caption) { + animation: 0.25s 0.25s linear both grow-x; +} +``` + +Here we've created a custom CSS animation and applied it to the `::view-transition-old(figure-caption)` and `::view-transition-new(figure-caption)` pseudo-elements. We've also added a number of other styles to both to keep them in the same place and stop the default styling from interfering with our custom animations. + +> **Note:** You can use `*` as the identifier in a pseudo-element to target all snapshot pseudo-elements, regardless of what name they have. For example: +> +> ```css +> ::view-transition-group(*) { +> animation-duration: 2s; +> } +> ``` + +### Taking advantage of the default animation styles + +Note that we also discovered another transition option that is simpler and produced a nicer result than the above. Our final `
` view transition ended up looking like this: + +```css +figcaption { + view-transition-name: figure-caption; +} + +::view-transition-group(figure-caption) { + height: 100%; +} +``` + +This works because, by default, `::view-transition-group` transitions `width` and `height` between the old and new views with a smooth scale. We just needed to set a fixed `height` on both states to make it work. + +> **Note:** [Smooth and simple transitions with the View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/) contains several other customization examples. + +## Controlling view transitions with JavaScript + +A view transition has an associated {{domxref("ViewTransition")}} object instance, which contains several promise members allowing you to run JavaScript in response to different states of the transition being reached. For example, {{domxref("ViewTransition.ready")}} fulfills once the pseudo-element tree is created and the animation is about to start, whereas {{domxref("ViewTransition.finished")}} fulfills once the animation is finished, and the new page view is visible and interactive to the user. + +The `ViewTransition` can be accessed like so: + +1. In the case of same-document (SPA) transitions, the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} method returns the `ViewTransition` associated with the transition. +2. In the case of cross-document (MPA) transitions: + +- A {{domxref("Window.pageswap_event", "pageswap")}} event is fired when a document is about to be unloaded due to a navigation. Its event object ({{domxref("PageSwapEvent")}}) provides access to the `ViewTransition` via the {{domxref("PageSwapEvent.viewTransition")}} property, as well as a {{domxref("NavigationActivation")}} via {{domxref("PageSwapEvent.activation")}} containing the navigation type and current and destination document history entries. + > **Note:** If the navigation has a cross-origin URL anywhere in the redirect chain, the `activation` property returns `null`. +- A {{domxref("Window.pagereveal_event", "pagereveal")}} event is fired when a document is first rendered, either when loading a fresh document from the network or activating a document (either from [bfcache](/en-US/docs/Glossary/bfcache) or [prerender](/en-US/docs/Glossary/Prerender)). Its event object ({{domxref("PageRevealEvent")}}) provides access to the `ViewTransition` via the {{domxref("PageRevealEvent.viewTransition")}} property. + +Let's have a look at some example code to show how these features could be used. + +### A JavaScript-powered custom same-document (SPA) transition + +The following JavaScript could be used to create a circular reveal view transition emanating from the position of the user's cursor on click, with animation provided by the {{domxref("Web Animations API", "Web Animations API", "", "nocode")}}. + +```js +// Store the last click event +let lastClick; +addEventListener("click", (event) => (lastClick = event)); + +function spaNavigate(data) { + // Fallback for browsers that don’t support this API: + if (!document.startViewTransition) { + updateTheDOMSomehow(data); + return; + } + + // Get the click position, or fallback to the middle of the screen + const x = lastClick?.clientX ?? innerWidth / 2; + const y = lastClick?.clientY ?? innerHeight / 2; + // Get the distance to the furthest corner + const endRadius = Math.hypot( + Math.max(x, innerWidth - x), + Math.max(y, innerHeight - y), + ); + + // Create a transition: + const transition = document.startViewTransition(() => { + updateTheDOMSomehow(data); + }); + + // Wait for the pseudo-elements to be created: + transition.ready.then(() => { + // Animate the root’s new view + document.documentElement.animate( + { + clipPath: [ + `circle(0 at ${x}px ${y}px)`, + `circle(${endRadius}px at ${x}px ${y}px)`, + ], + }, + { + duration: 500, + easing: "ease-in", + // Specify which pseudo-element to animate + pseudoElement: "::view-transition-new(root)", + }, + ); + }); +} +``` + +This animation also requires the following CSS, to turn off the default CSS animation and stop the old and new view states from blending in any way (the new state "wipes" right over the top of the old state, rather than transitioning in): + +```css +::view-transition-image-pair(root) { + isolation: auto; +} + +::view-transition-old(root), +::view-transition-new(root) { + animation: none; + mix-blend-mode: normal; + display: block; +} +``` + +### A JavaScript-powered custom cross-document (MPA) transition + +The [List of Chrome Dev Rel team members](https://view-transitions.netlify.app/profiles/mpa/) demo provides a basic set of team profile pages, and demonstrates how to use the {{domxref("Window.pageswap_event", "pageswap")}} and {{domxref("Window.pagereveal_event", "pagereveal")}} events to customize the outgoing and inbound animations of a cross-document view transition based on the "from" and "to" URLs. + +The {{domxref("Window.pageswap_event", "pageswap")}} event listener looks as follows. This sets view transition names on the elements on the outbound page that link to the profile pages. When navigating from the home page to a profile page, custom animations are provided _only_ for the linked element that is clicked in each case. + +```js +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:** We remove the `view-transition-name` values after snapshots have been taken in each case. If we left them set, they would persist in the page state saved in the [bfcache](/en-US/docs/Glossary/bfcache) upon navigation. If the back button was then pressed, the `pagereveal` event handler of the page being navigated back to would then attempt to set the same `view-transition-name` values on different elements. If multiple elements have the same `view-transition-name` set, the view transition is skipped. + +The {{domxref("Window.pagereveal_event", "pagereveal")}} event listener looks as follows. This works in a similar way to the `pageswap` event listener, although bear in mind that here we are customizing the "to" animation, for page elements on the new page. + +```js +window.addEventListener("pagereveal", async (e) => { + // If the "from" history entry does not exist, return + if (!navigation.activation.from) return; + + // Only run this if an active view transition exists + if (e.viewTransition) { + const fromUrl = new URL(navigation.activation.from.url); + const currentUrl = new URL(navigation.activation.entry.url); + + // Went from profile page to homepage + // ~> Set VT names on the relevant list item + if (isProfilePage(fromUrl) && isHomePage(currentUrl)) { + const profile = extractProfileNameFromUrl(fromUrl); + + // 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 names after snapshots have been taken + // so that we're ready for the next navigation + await e.viewTransition.ready; + document.querySelector(`#${profile} span`).style.viewTransitionName = + "none"; + document.querySelector(`#${profile} img`).style.viewTransitionName = + "none"; + } + + // Went to profile page + // ~> Set VT names on the main title and image + if (isProfilePage(currentUrl)) { + // 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 names after snapshots have been taken + // so that we're ready for the next navigation + await e.viewTransition.ready; + document.querySelector(`#detail main h1`).style.viewTransitionName = + "none"; + document.querySelector(`#detail main img`).style.viewTransitionName = + "none"; + } + } +}); +``` + +## Stabilizing page state to make cross-document transitions consistent + +Before running a cross-document transition, you ideally want to wait until the state of the page stabilizes, relying on [render blocking](/en-US/docs/Glossary/Render_blocking) to ensure that: + +1. Critical styles are loaded and applied. +2. Critical scripts are loaded and run. +3. The HTML visible for the user's initial view of the page has been parsed, so it renders consistently. + +Styles are render blocked by default, and scripts can be render blocked using the [`blocking="render"`](/en-US/docs/Web/HTML/Attributes/rel#blocking) attribute. + +To ensure that your initial HTML has been parsed and will always render consistently before the transition animation runs, you can use [``](/en-US/docs/Web/HTML/Attributes/rel#expect). In this element, you include the following attributes: + +- `rel="expect"` to indicate that you want to use this `` element to render block some HTML on the page. +- `href="#element-id"` to indicate the ID of the elment you want to render block. +- `blocking="render"` to render block the specified HTML. + +Let's explore what this looks like with a simple example HTML document: + +```html + + + + + + + + + + + +

Page title

+ +
+
The first section
+
The second section
+
+ + +``` + +The result is that document rendering is blocked until the lead content `
` has been parsed, ensuring a consistent view transition. + +You can also specify a [`media`](/en-US/docs/Web/HTML/Attributes/rel#blocking) attribute on `` elements. For example, you might want to block rendering on a smaller amount of content when loading the page on a narrow-screen device, than on a wide-screen device. This makes sense — on a mobile, less content will be visible when the page first loads than in the case of a desktop. + +This could be achieved with the following HTML: + +```html + + +``` diff --git a/files/en-us/web/api/viewtransition/finished/index.md b/files/en-us/web/api/viewtransition/finished/index.md index 441f20e8275bca9..a100601cb27040a 100644 --- a/files/en-us/web/api/viewtransition/finished/index.md +++ b/files/en-us/web/api/viewtransition/finished/index.md @@ -13,9 +13,9 @@ browser-compat: api.ViewTransition.finished The **`finished`** read-only property of the {{domxref("ViewTransition")}} interface is a {{jsxref("Promise")}} that fulfills once the transition animation is finished, and the new page view is visible and interactive to the user. -`finished` only rejects if the callback passed to {{domxref("Document.startViewTransition()", "document.startViewTransition()")}}throws or returns a promise that rejects, which indicates that the new state of the page wasn't created. +`finished` will only reject in the case of a same-document (SPA) transition, if the callback passed to {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} throws or returns a promise that rejects. This would indicate that the new state of the page wasn't created. -If a transition animation fails to start, or is skipped during the animation using {{domxref("ViewTransition.skipTransition()")}}, the end state is still reached therefore `finished` still fulfills. +If a transition animation fails to start or is skipped during the transition using {{domxref("ViewTransition.skipTransition()")}}, the end state is still reached therefore `finished` will still fulfill. ## Value @@ -25,7 +25,7 @@ A Promise. ### Different transitions for different navigations -Sometimes certain navigations will require specifically tailored transitions, for example a 'back' navigation may want a different transition to a 'forward' navigation. The best way to handle such cases is to set a class name on the `` element, handle the transition — applying the correct animation using a tailored selector — and then remove the class name once the transition is finished. +Sometimes certain navigations will require specifically tailored transitions, for example, a 'back' navigation may want a different transition to a 'forward' navigation. The best way to handle such cases is to set a class name on the `` element, handle the transition — applying the correct animation using a tailored selector — and then remove the class name once the transition is finished. ```js async function handleTransition() { @@ -45,7 +45,7 @@ async function handleTransition() { } ``` -> **Note:** `isBackNavigation` isn't a built-in feature; it's a theoretical function that could perhaps be implemented using the [Navigation API](/en-US/docs/Web/API/Navigation_API) or similar. +> **Note:** `isBackNavigation` isn't a built-in feature; it's a theoretical function that could be implemented using the [Navigation API](/en-US/docs/Web/API/Navigation_API) or similar. ## Specifications diff --git a/files/en-us/web/api/viewtransition/index.md b/files/en-us/web/api/viewtransition/index.md index 685a0d11b728775..6b4785b4d48c742 100644 --- a/files/en-us/web/api/viewtransition/index.md +++ b/files/en-us/web/api/viewtransition/index.md @@ -9,9 +9,16 @@ browser-compat: api.ViewTransition {{APIRef("View Transitions API")}}{{SeeCompatTable}} -The **`ViewTransition`** interface of the {{domxref("View Transitions API", "View Transitions API", "", "nocode")}} represents a view transition, and provides functionality to react to the transition reaching different states (e.g. ready to run the animation, or animation finished) or skip the transition altogether. +The **`ViewTransition`** interface of the {{domxref("View Transitions API", "View Transitions API", "", "nocode")}} represents an active view transition, and provides functionality to react to the transition reaching different states (e.g. ready to run the animation, or animation finished) or skip the transition altogether. -This object type is returned by the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} method. When `startViewTransition()` is invoked, a sequence of steps is followed as explained in [The view transition process](/en-US/docs/Web/API/View_Transitions_API#the_view_transition_process). This also explains when the different promises fulfill. +This object type is made available in the following ways: + +- In the case of same-document (SPA) transitions, it is returned by the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} method. +- In the case of cross-document (MPA) transitions, it is made available: + - In the outgoing page via the {{domxref("Window.pageswap_event", "pageswap")}} event object's {{domxref("PageSwapEvent.viewTransition")}} property. + - In the inbound page via the {{domxref("Window.pagereveal_event", "pagereveal")}} event object's {{domxref("PageRevealEvent.viewTransition")}} property. + +When a view transition is triggered by a `startViewTransition()` call (or a page navigation in the case of MPA transitions), a sequence of steps is followed as explained in [The view transition process](/en-US/docs/Web/API/View_Transitions_API/Using#the_view_transition_process). This also explains when the different promises fulfill. ## Instance properties @@ -20,16 +27,16 @@ This object type is returned by the {{domxref("Document.startViewTransition()", - {{domxref("ViewTransition.ready")}} {{ReadOnlyInline}} {{Experimental_Inline}} - : A {{jsxref("Promise")}} that fulfills once the pseudo-element tree is created and the transition animation is about to start. - {{domxref("ViewTransition.updateCallbackDone")}} {{ReadOnlyInline}} {{Experimental_Inline}} - - : A {{jsxref("Promise")}} that fulfills when the promise returned by the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}}'s callback fulfills. + - : A {{jsxref("Promise")}} that fulfills when the promise returned by the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} method's callback fulfills. ## Instance methods - {{domxref("ViewTransition.skipTransition", "skipTransition()")}} {{Experimental_Inline}} - - : Skips the animation part of the view transition, but doesn't skip running the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} callback that updates the DOM. + - : Skips the animation part of the view transition, but doesn't skip running the associated view update. ## Examples -In the following example, the {{domxref("ViewTransition.ready")}} promise is used to trigger a custom circular reveal view transition emanating from the position of the user's cursor on click, with animation provided by the {{domxref("Web Animations API", "Web Animations API", "", "nocode")}}. +In the following SPA example, the {{domxref("ViewTransition.ready")}} promise is used to trigger a custom circular reveal view transition emanating from the position of the user's cursor on click, with animation provided by the {{domxref("Web Animations API", "Web Animations API", "", "nocode")}}. ```js // Store the last click event diff --git a/files/en-us/web/api/viewtransition/ready/index.md b/files/en-us/web/api/viewtransition/ready/index.md index bc82202b0ffa1ce..fd942b308675889 100644 --- a/files/en-us/web/api/viewtransition/ready/index.md +++ b/files/en-us/web/api/viewtransition/ready/index.md @@ -13,7 +13,7 @@ browser-compat: api.ViewTransition.ready The **`ready`** read-only property of the {{domxref("ViewTransition")}} interface is a {{jsxref("Promise")}} that fulfills once the pseudo-element tree is created and the transition animation is about to start. -`ready` will reject if the transition cannot begin. This can be due to misconfiguration, for example duplicate {{cssxref("view-transition-name")}}s, or if the callback passed to {{domxref("Document.startViewTransition()")}} throws or returns a promise that rejects. +`ready` will reject if the transition cannot begin. This can be due to misconfiguration, for example, duplicate {{cssxref("view-transition-name")}}s, or if the callback passed to {{domxref("Document.startViewTransition()")}} throws or returns a promise that rejects. ## Value diff --git a/files/en-us/web/api/viewtransition/skiptransition/index.md b/files/en-us/web/api/viewtransition/skiptransition/index.md index 2e2c7f8498ef99e..387f973c96363b7 100644 --- a/files/en-us/web/api/viewtransition/skiptransition/index.md +++ b/files/en-us/web/api/viewtransition/skiptransition/index.md @@ -11,7 +11,7 @@ browser-compat: api.ViewTransition.skipTransition {{APIRef("View Transitions API")}}{{SeeCompatTable}} The **`skipTransition()`** method of the -{{domxref("ViewTransition")}} interface skips the animation part of the view transition, but doesn't skip running the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} callback that updates the DOM. +{{domxref("ViewTransition")}} interface skips the animation part of the view transition, but doesn't skip running the associated view update. ## Syntax @@ -29,6 +29,8 @@ None. ## Examples +### Skipping an SPA view transition + ```js // start new view transition const transition = document.startViewTransition(() => displayNewImage()); @@ -37,6 +39,20 @@ const transition = document.startViewTransition(() => displayNewImage()); transition.skipTransition(); ``` +### Skipping an MPA view transition + +```js +// Fired on the current (outgoing) page +document.addEventListener("pageswap", (event) => { + event.viewTransition?.skipTransition(); +}); + +// Fired on the destination (inbound) page +document.addEventListener("pagereveal", (event) => { + event.viewTransition?.skipTransition(); +}); +``` + ## Specifications {{Specifications}} diff --git a/files/en-us/web/api/viewtransition/updatecallbackdone/index.md b/files/en-us/web/api/viewtransition/updatecallbackdone/index.md index 44d7c0775221096..eeba8cf7bca257a 100644 --- a/files/en-us/web/api/viewtransition/updatecallbackdone/index.md +++ b/files/en-us/web/api/viewtransition/updatecallbackdone/index.md @@ -11,9 +11,11 @@ browser-compat: api.ViewTransition.updateCallbackDone {{APIRef("View Transitions API")}}{{SeeCompatTable}} The **`updateCallbackDone`** read-only property of the -{{domxref("ViewTransition")}} interface is a {{jsxref("Promise")}} that fulfills when the promise returned by the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}}'s callback fulfills, or rejects when it rejects. +{{domxref("ViewTransition")}} interface is a {{jsxref("Promise")}} that fulfills when the promise returned by the {{domxref("Document.startViewTransition()", "document.startViewTransition()")}} method's callback fulfills, or rejects when it rejects. -`updateCallbackDone` is useful when you don't care about the success/failure of the transition animation, and just want to know if and when the DOM is updated. +`updateCallbackDone` is useful when you don't care about the success/failure of a same-document (SPA) view transition animation, and just want to know if and when the DOM is updated. + +> **Note:** In the case of a cross-document (MPA) view transition, the `updateCallbackDone` promise of the associated `ViewTransition` is automatically fulfilled. ## Value @@ -22,7 +24,7 @@ A Promise. ## Examples ```js -// start new view transition +// start new SPA view transition const transition = document.startViewTransition(() => displayNewImage()); transition.updateCallbackDone.then(() => { diff --git a/files/en-us/web/api/window/index.md b/files/en-us/web/api/window/index.md index 082e1129cf828d3..6d73db12f624a1b 100644 --- a/files/en-us/web/api/window/index.md +++ b/files/en-us/web/api/window/index.md @@ -348,8 +348,12 @@ Listen to these events using [`addEventListener()`](/en-US/docs/Web/API/EventTar - : Fired when the fragment identifier of the URL has changed (the part of the URL beginning with and following the `#` symbol). - {{domxref("Window/pagehide_event", "pagehide")}} - : Sent when the browser hides the current document while in the process of switching to displaying in its place a different document from the session's history. This happens, for example, when the user clicks the Back button or when they click the Forward button to move ahead in session history. +- {{domxref("Window.pagereveal_event", "pagereveal")}} {{experimental_inline}} + - : Fired when a document is first rendered, either when loading a fresh document from the network or activating a document (either from [bfcache](https://web.dev/articles/bfcache) or [prerender](/en-US/docs/Glossary/Prerender)). - {{domxref("Window/pageshow_event", "pageshow")}} - : Sent when the browser makes the document visible due to navigation tasks, including not only when the page is first loaded, but also situations such as the user navigating back to the page after having navigated to another within the same tab. +- {{domxref("Window.pageswap_event", "pageswap")}} {{experimental_inline}} + - : Fired when a document is about to be unloaded due to a navigation. - {{domxref("Window/popstate_event", "popstate")}} - : Fired when the active history entry changes. diff --git a/files/en-us/web/api/window/pagereveal_event/index.md b/files/en-us/web/api/window/pagereveal_event/index.md new file mode 100644 index 000000000000000..3be4e0d171a5d5f --- /dev/null +++ b/files/en-us/web/api/window/pagereveal_event/index.md @@ -0,0 +1,103 @@ +--- +title: "Window: pagereveal event" +short-title: pagereveal +slug: Web/API/Window/pagereveal_event +page-type: web-api-event +status: + - experimental +browser-compat: api.Window.pagereveal_event +--- + +{{APIRef("HTML DOM")}}{{seecompattable}} + +The **`pagereveal`** event is fired when a document is first rendered, either when loading a fresh document from the network or activating a document (either from [bfcache](https://web.dev/articles/bfcache) or [prerender](/en-US/docs/Glossary/Prerender)). + +This is useful in the case of cross-document (MPA) [view transitions](/en-US/docs/Web/API/View_Transitions_API) for manipulating an active transition from the inbound page of a navigation. For example, you might wish to skip the transition, or customize the inbound transition animation via JavaScript. + +## Syntax + +Use the event name in methods like {{domxref("EventTarget.addEventListener", "addEventListener()")}}, or set an event handler property. + +```js +addEventListener("pagereveal", (event) => {}); +onpagereveal = (event) => {}; +``` + +## Event type + +A {{domxref("PageRevealEvent")}}. Inherits from {{domxref("Event")}}. + +{{InheritanceDiagram("PageRevealEvent")}} + +## Event properties + +- {{domxref("PageRevealEvent.viewTransition")}} {{ReadOnlyInline}} + - : Returns the {{domxref("ViewTransition")}} object representing the inbound cross-document view transition, if one is active when the event is fired. If this is not the case, it returns `null`. + +## Examples + +```js +window.addEventListener("pagereveal", async (e) => { + // If the "from" history entry does not exist, return + if (!navigation.activation.from) return; + + // Only run this if an active view transition exists + if (e.viewTransition) { + const fromUrl = new URL(navigation.activation.from.url); + const currentUrl = new URL(navigation.activation.entry.url); + + // Went from profile page to homepage + // ~> Set VT names on the relevant list item + if (isProfilePage(fromUrl) && isHomePage(currentUrl)) { + const profile = extractProfileNameFromUrl(fromUrl); + + // 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 names after snapshots have been taken + // so that we're ready for the next navigation + await e.viewTransition.ready; + document.querySelector(`#${profile} span`).style.viewTransitionName = + "none"; + document.querySelector(`#${profile} img`).style.viewTransitionName = + "none"; + } + + // Went to profile page + // ~> Set VT names on the main title and image + if (isProfilePage(currentUrl)) { + // 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 names after snapshots have been taken + // so that we're ready for the next navigation + await e.viewTransition.ready; + document.querySelector(`#detail main h1`).style.viewTransitionName = + "none"; + document.querySelector(`#detail main img`).style.viewTransitionName = + "none"; + } + } +}); +``` + +> **Note:** See [List of Chrome Dev Rel team members](https://view-transitions.netlify.app/profiles/mpa/) for the live demo this code is taken from. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Using the View Transitions API](/en-US/docs/Web/API/View_Transitions_API/Using) +- {{domxref("Window.pageswap_event", "pageswap")}} event diff --git a/files/en-us/web/api/window/pageswap_event/index.md b/files/en-us/web/api/window/pageswap_event/index.md new file mode 100644 index 000000000000000..bb4539e235c936a --- /dev/null +++ b/files/en-us/web/api/window/pageswap_event/index.md @@ -0,0 +1,106 @@ +--- +title: "Window: pageswap event" +short-title: pageswap +slug: Web/API/Window/pageswap_event +page-type: web-api-event +status: + - experimental +browser-compat: api.Window.pageswap_event +--- + +{{APIRef("HTML DOM")}}{{seecompattable}} + +The **`pageswap`** event is fired when you navigate across documents, when the previous document is about to unload. + +This is useful in the case of cross-document (MPA) [view transitions](/en-US/docs/Web/API/View_Transitions_API) for manipulating an active transition from the outbound page of a navigation. For example, you might wish to skip the transition, or customize the outbound transition animation via JavaScript. + +It also provides access to the navigation type and current and destination document history entries. + +## Syntax + +Use the event name in methods like {{domxref("EventTarget.addEventListener", "addEventListener()")}}, or set an event handler property. + +```js +addEventListener("pageswap", (event) => {}); +onpageswap = (event) => {}; +``` + +## Event type + +A {{domxref("PageSwapEvent")}}. Inherits from {{domxref("Event")}}. + +{{InheritanceDiagram("PageSwapEvent")}} + +## Event properties + +- {{domxref("PageSwapEvent.activation")}} {{ReadOnlyInline}} + - : Returns a {{domxref("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`. +- {{domxref("PageSwapEvent.viewTransition")}} {{ReadOnlyInline}} + - : Returns the {{domxref("ViewTransition")}} object representing the inbound cross-document view transition, if one is active when the event is fired. If this is not the case, it returns `null`. + +## Examples + +```js +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 Dev Rel team members](https://view-transitions.netlify.app/profiles/mpa/) for the live demo this code is taken from. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [Using the View Transitions API](/en-US/docs/Web/API/View_Transitions_API/Using) +- {{domxref("Window.pagereveal_event", "pagereveal")}} event diff --git a/files/en-us/web/css/@view-transition/index.md b/files/en-us/web/css/@view-transition/index.md new file mode 100644 index 000000000000000..87983e973d0de9d --- /dev/null +++ b/files/en-us/web/css/@view-transition/index.md @@ -0,0 +1,60 @@ +--- +title: "@view-transition" +slug: Web/CSS/@view-transition +page-type: css-at-rule +browser-compat: css.at-rules.view-transition +--- + +{{CSSRef}} + +The **`@view-transition`** [CSS](/en-US/docs/Web/CSS) [at-rule](/en-US/docs/Web/CSS/At-rule) is used to opt in the current and destination documents to undergo a [view transition](/en-US/docs/Web/API/View_Transitions_API), in the case of a cross-document navigation. + +For a cross-document view transition to work, the current and destination documents of the navigation also need to be on the same origin. + +## Syntax + +```css +@view-transition { + navigation: auto; +} +``` + +### Descriptors + +- `navigation` + + - : Specifies the effect this at-rule will have on the document's view transition behavior. Possible values are: + + - `auto`: The document will undergo a view transition when taking part in a navigation, provided the navigation is same-origin, without cross-origin redirects, and its {{domxref("NavigateEvent.navigationType", "navigationType")}} is `traverse`, `push`, or `replace`. In the case of `push` or `replace`, the navigation must be initiated by a user interacting with the page content, not by a browser UI feature. + + - `none`: The document will not undergo a view transition. + +## Formal syntax + +{{csssyntax}} + +## Examples + +### Basic usage + +```css +@view-transition { + navigation: auto; +} +``` + +You need to specify the above `@view-transition` at-rule in the CSS for both the current and destination documents of a navigation to opt them in to the view transition. + +> **Note:** Our [View Transitions MPA demo](https://mdn.github.io/dom-examples/view-transitions/mpa/) shows this at-rule in action, and additionally demonstrates how to customize the outbound and inbound animations of the view transition. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [View Transitions API](/en-US/docs/Web/API/View_Transitions_API) diff --git a/files/en-us/web/css/_doublecolon_view-transition-group/index.md b/files/en-us/web/css/_doublecolon_view-transition-group/index.md index e35c5146060a29a..b53a358486394b5 100644 --- a/files/en-us/web/css/_doublecolon_view-transition-group/index.md +++ b/files/en-us/web/css/_doublecolon_view-transition-group/index.md @@ -9,9 +9,9 @@ browser-compat: css.selectors.view-transition-group {{CSSRef}}{{SeeCompatTable}} -The **`::view-transition-group`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents a single view transition group. +The **`::view-transition-group`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents a single view transition snapshot group. -During a view transition, `::view-transition-group` is included in the associated pseudo-element tree as explained in [The view transition process](/en-US/docs/Web/API/View_Transitions_API#the_view_transition_process). It is only ever a child of {{cssxref("::view-transition")}}, and has a {{cssxref("::view-transition-image-pair")}} as a child. +During a view transition, `::view-transition-group` is included in the associated pseudo-element tree as explained in [The view transition pseudo-element tree](/en-US/docs/Web/API/View_Transitions_API/Using#the_view_transition_pseudo-element_tree). It is only ever a child of {{cssxref("::view-transition")}}, and has a {{cssxref("::view-transition-image-pair")}} as a child. `::view-transition-group` is given the following default styling in the UA stylesheet: @@ -30,7 +30,7 @@ By default, selected elements initially mirror the size and position of the {{cs If there's both an "old" and "new" view state, styles in the view transition style sheet animate this pseudo-element's {{cssxref("width")}} and {{cssxref("height")}} from the size of the "old" view state's border box to that of the "new" view state's border box. -> **Note:** View transition style sheet styles are dynamically generated during the view transition; see the specification [setup transition pseudo-elements](https://drafts.csswg.org/css-view-transitions-1/#setup-transition-pseudo-elements) and [update pseudo-element styles](https://drafts.csswg.org/css-view-transitions-1/#update-pseudo-element-styles) sections for more details. +> **Note:** View transition styles are dynamically generated during the view transition; see the specification [setup transition pseudo-elements](https://drafts.csswg.org/css-view-transitions-1/#setup-transition-pseudo-elements) and [update pseudo-element styles](https://drafts.csswg.org/css-view-transitions-1/#update-pseudo-element-styles) sections for more details. In addition, the element's transform is animated from the "old" view state's screen space transform to the new view state's screen space transform. This style is generated dynamically since the values of animated properties are determined at the time that the transition begins. @@ -47,7 +47,7 @@ In addition, the element's transform is animated from the "old" view state's scr - `*` - : Causes the pseudo-element to match all view transition groups. - `root` - - : Causes the pseudo-element to match the default `root` view transition group created by the user agent to contain the view transition for the overall page, meaning any element not assigned to its own specific view transition group via the {{cssxref("view-transition-name")}} property. + - : Causes the pseudo-element to match the default `root` view transition group created by the user agent to contain the view transition for the overall page. This group includes any element not assigned to its own specific view transition group via the {{cssxref("view-transition-name")}} property. - {{cssxref("custom-ident")}} - : Causes the pseudo-element to match a specific view transition group created by assigning the given {{cssxref("custom-ident")}} to an element via the {{cssxref("view-transition-name")}} property. diff --git a/files/en-us/web/css/_doublecolon_view-transition-image-pair/index.md b/files/en-us/web/css/_doublecolon_view-transition-image-pair/index.md index b2bddafa4617966..b04254c32b9f5cc 100644 --- a/files/en-us/web/css/_doublecolon_view-transition-image-pair/index.md +++ b/files/en-us/web/css/_doublecolon_view-transition-image-pair/index.md @@ -11,17 +11,18 @@ browser-compat: css.selectors.view-transition-image-pair The **`::view-transition-image-pair`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents a container for a [view transition's](/en-US/docs/Web/API/View_Transitions_API) "old" and "new" view states — before and after the transition. -During a view transition, `::view-transition-image-pair` is included in the associated pseudo-element tree as explained in [The view transition process](/en-US/docs/Web/API/View_Transitions_API#the_view_transition_process). It is only ever a child of a {{cssxref("::view-transition-group")}}. In terms of children, it can have a {{cssxref("::view-transition-new")}} or a {{cssxref("::view-transition-old")}}, or both. +During a view transition, `::view-transition-image-pair` is included in the associated pseudo-element tree as explained in [The view transition pseudo-element tree](/en-US/docs/Web/API/View_Transitions_API/Using#the_view_transition_pseudo-element_tree). It is only ever a child of a {{cssxref("::view-transition-group")}}. In terms of children, it can have a {{cssxref("::view-transition-new")}} or a {{cssxref("::view-transition-old")}}, or both. `::view-transition-image-pair` is given the following default styling in the UA stylesheet: ```css -html::view-transition-image-pair(*) { +:root::view-transition-image-pair(*) { position: absolute; inset: 0; animation-duration: inherit; animation-fill-mode: inherit; + animation-delay: inherit; } ``` @@ -40,7 +41,7 @@ During a view transition, `::view-transition-image-pair` has {{cssxref("isolatio - `*` - : Causes the pseudo-element to match all view transition groups. - `root` - - : Causes the pseudo-element to match the default `root` view transition group created by the user agent to contain the view transition for the overall page, meaning any element not assigned to its own specific view transition group via the {{cssxref("view-transition-name")}} property. + - : Causes the pseudo-element to match the default `root` view transition group created by the user agent to contain the view transition for the overall page. This group includes any element not assigned to its own specific view transition group via the {{cssxref("view-transition-name")}} property. - {{cssxref("custom-ident")}} - : Causes the pseudo-element to match a specific view transition group created by assigning the given {{cssxref("custom-ident")}} to an element via the {{cssxref("view-transition-name")}} property. diff --git a/files/en-us/web/css/_doublecolon_view-transition-new/index.md b/files/en-us/web/css/_doublecolon_view-transition-new/index.md index ece636dfcc35b1c..3662d509b1b3814 100644 --- a/files/en-us/web/css/_doublecolon_view-transition-new/index.md +++ b/files/en-us/web/css/_doublecolon_view-transition-new/index.md @@ -9,34 +9,45 @@ browser-compat: css.selectors.view-transition-new {{CSSRef}}{{SeeCompatTable}} -The **`::view-transition-new`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents the "new" view state of a view transition — a live representation of the new view, after the transition. +The **`::view-transition-new`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents the "new" view state of a view transition — a snapshot live representation of the state after the transition. -During a view transition, `::view-transition-new` is included in the associated pseudo-element tree as explained in [The view transition process](/en-US/docs/Web/API/View_Transitions_API#the_view_transition_process). It is only ever a child of a {{cssxref("::view-transition-image-pair")}}, and never has any children. +During a view transition, `::view-transition-new` is included in the associated pseudo-element tree as explained in [The view transition pseudo-element tree](/en-US/docs/Web/API/View_Transitions_API/Using#the_view_transition_pseudo-element_tree). It is only ever a child of a {{cssxref("::view-transition-image-pair")}}, and never has any children. -It is a replaced element, and therefore can be manipulated with properties such as {{cssxref("object-fit")}} and {{cssxref("object-position")}}. It has natural dimensions equal to the content's size. +It is a replaced element and therefore can be manipulated with properties such as {{cssxref("object-fit")}} and {{cssxref("object-position")}}. It has natural dimensions equal to the content's size. The following default styling is included in the UA stylesheet: ```css -@keyframes -ua-view-transition-fade-in { - from { - opacity: 0; - } -} - -html::view-transition-new(*) { +:root::view-transition-old(*), +:root::view-transition-new(*) { position: absolute; inset-block-start: 0; inline-size: 100%; block-size: auto; - animation-name: -ua-view-transition-fade-in; animation-duration: inherit; animation-fill-mode: inherit; + animation-delay: inherit; +} + +/* Keyframes for blending when there are 2 images */ +@keyframes -ua-mix-blend-mode-plus-lighter { + from { + mix-blend-mode: plus-lighter; + } + to { + mix-blend-mode: plus-lighter; + } +} + +@keyframes -ua-view-transition-fade-in { + from { + opacity: 0; + } } ``` -> **Note:** Additional view transition style sheet styles are also setup to animate `::view-transition-new`. These are dynamically generated during the view transition; see the specification [setup transition pseudo-elements](https://drafts.csswg.org/css-view-transitions-1/#setup-transition-pseudo-elements) and [update pseudo-element styles](https://drafts.csswg.org/css-view-transitions-1/#update-pseudo-element-styles) sections for more details. +> **Note:** Additional view transition styles are also setup to animate `::view-transition-new`. These are dynamically generated during the view transition; see the specification [setup transition pseudo-elements](https://drafts.csswg.org/css-view-transitions-1/#setup-transition-pseudo-elements) and [update pseudo-element styles](https://drafts.csswg.org/css-view-transitions-1/#update-pseudo-element-styles) sections for more details. ## Syntax @@ -51,9 +62,9 @@ html::view-transition-new(*) { - `*` - : Causes the pseudo-element to match all view transition groups. - `root` - - : Causes the pseudo-element to match the default `root` view transition group created by the user agent to contain the view transition for the overall page, meaning any element not assigned to its own specific view transition group via the {{cssxref("view-transition-name")}} property. + - : Causes the pseudo-element to match the default `root` view transition snapshot group created by the user agent to contain the view transition for the overall page. This group includes any element not assigned to its own specific view transition snapshot group via the {{cssxref("view-transition-name")}} property. - {{cssxref("custom-ident")}} - - : Causes the pseudo-element to match a specific view transition group created by assigning the given {{cssxref("custom-ident")}} to an element via the {{cssxref("view-transition-name")}} property. + - : Causes the pseudo-element to match a specific view transition snapshot group created by assigning the given {{cssxref("custom-ident")}} to an element via the {{cssxref("view-transition-name")}} property. ## Examples diff --git a/files/en-us/web/css/_doublecolon_view-transition-old/index.md b/files/en-us/web/css/_doublecolon_view-transition-old/index.md index 736763ce535e926..1548307440ae049 100644 --- a/files/en-us/web/css/_doublecolon_view-transition-old/index.md +++ b/files/en-us/web/css/_doublecolon_view-transition-old/index.md @@ -9,34 +9,45 @@ browser-compat: css.selectors.view-transition-old {{CSSRef}}{{SeeCompatTable}} -The **`::view-transition-old`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents the "old" view state of a view transition — a static screenshot of the old view, before the transition. +The **`::view-transition-old`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents the "old" view state of a view transition — a static snapshot of the old view, before the transition. -During a view transition, `::view-transition-old` is included in the associated pseudo-element tree as explained in [The view transition process](/en-US/docs/Web/API/View_Transitions_API#the_view_transition_process), provided there's an "old" view state to represent. It is only ever a child of a {{cssxref("::view-transition-image-pair")}}, and never has any children. +During a view transition, `::view-transition-old` is included in the associated pseudo-element tree as explained in [The view transition pseudo-element tree](/en-US/docs/Web/API/View_Transitions_API/Using#the_view_transition_pseudo-element_tree), provided there's an "old" view state to represent. It is only ever a child of a {{cssxref("::view-transition-image-pair")}}, and never has any children. -It is a replaced element, and therefore can be manipulated with properties such as {{cssxref("object-fit")}} and {{cssxref("object-position")}}. It has natural dimensions equal to the content's size. +It is a replaced element and therefore can be manipulated with properties such as {{cssxref("object-fit")}} and {{cssxref("object-position")}}. It has natural dimensions equal to the content's size. The following default styling is included in the UA stylesheet: ```css -@keyframes -ua-view-transition-fade-out { - to { - opacity: 0; - } -} - -html::view-transition-old(*) { +:root::view-transition-old(*), +:root::view-transition-new(*) { position: absolute; inset-block-start: 0; inline-size: 100%; block-size: auto; - animation-name: -ua-view-transition-fade-out; animation-duration: inherit; animation-fill-mode: inherit; + animation-delay: inherit; +} + +/* Keyframes for blending when there are 2 images */ +@keyframes -ua-mix-blend-mode-plus-lighter { + from { + mix-blend-mode: plus-lighter; + } + to { + mix-blend-mode: plus-lighter; + } +} + +@keyframes -ua-view-transition-fade-out { + to { + opacity: 0; + } } ``` -> **Note:** Additional view transition style sheet styles are also setup to animate `::view-transition-old`. These are dynamically generated during the view transition; see the specification [setup transition pseudo-elements](https://drafts.csswg.org/css-view-transitions-1/#setup-transition-pseudo-elements) and [update pseudo-element styles](https://drafts.csswg.org/css-view-transitions-1/#update-pseudo-element-styles) sections for more details. +> **Note:** Additional view transition styles are also setup to animate `::view-transition-old`. These are dynamically generated during the view transition; see the specification [setup transition pseudo-elements](https://drafts.csswg.org/css-view-transitions-1/#setup-transition-pseudo-elements) and [update pseudo-element styles](https://drafts.csswg.org/css-view-transitions-1/#update-pseudo-element-styles) sections for more details. ## Syntax @@ -51,9 +62,9 @@ html::view-transition-old(*) { - `*` - : Causes the pseudo-element to match all view transition groups. - `root` - - : Causes the pseudo-element to match the default `root` view transition group created by the user agent to contain the view transition for the overall page, meaning any element not assigned to its own specific view transition group via the {{cssxref("view-transition-name")}} property. + - : Causes the pseudo-element to match the default `root` view transition snapshot group created by the user agent to contain the view transition for the overall page. This group includes any element not assigned to its own specific view transition snapshot group via the {{cssxref("view-transition-name")}} property. - {{cssxref("custom-ident")}} - - : Causes the pseudo-element to match a specific view transition group created by assigning the given {{cssxref("custom-ident")}} to an element via the {{cssxref("view-transition-name")}} property. + - : Causes the pseudo-element to match a specific view transition snapshot group created by assigning the given {{cssxref("custom-ident")}} to an element via the {{cssxref("view-transition-name")}} property. ## Examples diff --git a/files/en-us/web/css/_doublecolon_view-transition/index.md b/files/en-us/web/css/_doublecolon_view-transition/index.md index 0bd00af1a053401..178c839d48936d3 100644 --- a/files/en-us/web/css/_doublecolon_view-transition/index.md +++ b/files/en-us/web/css/_doublecolon_view-transition/index.md @@ -9,9 +9,9 @@ browser-compat: css.selectors.view-transition {{CSSRef}}{{SeeCompatTable}} -The **`::view-transition`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents the root of the [view transitions](/en-US/docs/Web/API/View_Transitions_API) overlay, which contains all view transitions and sits over the top of all other page content. +The **`::view-transition`** [CSS](/en-US/docs/Web/CSS) [pseudo-element](/en-US/docs/Web/CSS/Pseudo-elements) represents the root of the [view transitions](/en-US/docs/Web/API/View_Transitions_API) overlay, which contains all view transition snapshot groups and sits over the top of all other page content. -During a view transition, `::view-transition` is included in the associated pseudo-element tree as explained in [The view transition process](/en-US/docs/Web/API/View_Transitions_API#the_view_transition_process). It is the top-level node of this tree, and has one or more {{cssxref("::view-transition-group")}}s as children. +During a view transition, `::view-transition` is included in the associated pseudo-element tree as explained in [The view transition pseudo-element tree](/en-US/docs/Web/API/View_Transitions_API/Using#the_view_transition_pseudo-element_tree). It is the top-level node of this tree, and has one or more {{cssxref("::view-transition-group")}}s as children. `::view-transition` is given the following default styling in the UA stylesheet: diff --git a/files/en-us/web/css/view-transition-name/index.md b/files/en-us/web/css/view-transition-name/index.md index 7bb22beb3830642..7149b857b2445f5 100644 --- a/files/en-us/web/css/view-transition-name/index.md +++ b/files/en-us/web/css/view-transition-name/index.md @@ -25,7 +25,8 @@ view-transition-name: none; ### Values - {{cssxref("custom-ident")}} - - : A distinct identifying name that causes the selected element to participate in a separate [view transition](/en-US/docs/Web/API/View_Transitions_API) from the root view transition. The identifier must be unique. If two rendered elements have the same `view-transition-name` at the same time, {{domxref("ViewTransition.ready")}} will reject and the transition will be skipped. + - : An identifying name that causes the selected element to participate in a separate [view transition](/en-US/docs/Web/API/View_Transitions_API) from the root view transition. The identifier must be unique. If two rendered elements have the same `view-transition-name` at the same time, {{domxref("ViewTransition.ready")}} will reject and the transition will be skipped. + > **Note:** The `` cannot be `auto`. - `none` - : The selected element will not participate in a view transition. diff --git a/files/en-us/web/html/attributes/rel/index.md b/files/en-us/web/html/attributes/rel/index.md index 4e9fb7ebca8751a..1656462b78c3132 100644 --- a/files/en-us/web/html/attributes/rel/index.md +++ b/files/en-us/web/html/attributes/rel/index.md @@ -24,6 +24,7 @@ The following table lists some of the most important existing keywords. Every ke | [`canonical`](#canonical) | Preferred URL for the current document. | Link | Not allowed | Not allowed | | [`dns-prefetch`](/en-US/docs/Web/HTML/Attributes/rel/dns-prefetch) | Tells the browser to preemptively perform DNS resolution for the target resource's origin. | External Resource | Not allowed | Not allowed | | [`external`](#external) | The referenced document is not part of the same site as the current document. | Not allowed | Annotation | Annotation | +| [`expect`](#expect) | Allows the page to be [render-blocked](/en-US/docs/Glossary/Render_blocking) until the essential parts of the document are parsed so it will render consistently. | Link | Not allowed | Not allowed | | [`help`](#help) | Link to context-sensitive help. | Link | Link | Link | | [`icon`](#icon) | An icon representing the current document. | External Resource | Not allowed | Not allowed | | [`license`](#license) | Indicates that the main content of the current document is covered by the copyright license described by the referenced document. | Link | Link | Link | @@ -120,6 +121,12 @@ The `rel` attribute has no default value. If the attribute is omitted or if none - : Relevant for the {{htmlelement('link')}} element both in the {{htmlelement('body')}} and {{htmlelement('head')}}, it tells the browser to preemptively perform DNS resolution for the target resource's origin. Useful for resources the user will likely need, it helps reduce latency and thereby improves performance when the user does access the resources as the browser preemptively performed DNS resolution for the origin of the specified resource. See [dns-prefetch](/en-US/docs/Web/Performance/dns-prefetch) described in [resource hints](https://w3c.github.io/resource-hints/). - `external` - : Relevant to {{htmlelement('form')}}, {{htmlelement('a')}}, and {{htmlelement('area')}}, it indicates the referenced document is not part of the current site. This can be used with attribute selectors to style external links in a way that indicates to the user that they will be leaving the current site. +- `expect` + + - : Allows the page to be [render-blocked](/en-US/docs/Glossary/Render_blocking) until the essential parts of the document are parsed so it will render consistently. Note that render-blocking occurs only when supplemented with the [`blocking="render"`](/en-US/docs/Web/HTML/Attributes/rel#blocking) attribute. + + > **Note:** See [Stabilizing page state to make cross-document transitions consistent](/en-US/docs/Web/API/View_Transitions_API/Using#stabilizing_page_state_to_make_cross-document_transitions_consistent) for more information on its use. + - `help` - : Relevant to {{htmlelement('form')}}, {{htmlelement('link')}}, {{htmlelement('a')}}, and {{htmlelement('area')}}, the `help` keyword indicates that the linked to content provides context-sensitive help, providing information for the parent of the element defining the hyperlink, and its children. When used within ``, the help is for the whole document. When included with {{htmlelement('a')}} and {{htmlelement('area')}} and supported, the default {{cssxref('cursor')}} will be `help` instead of `pointer`. - `icon` diff --git a/files/jsondata/GroupData.json b/files/jsondata/GroupData.json index fdabe38c9c7935b..950cc378f49f2cd 100644 --- a/files/jsondata/GroupData.json +++ b/files/jsondata/GroupData.json @@ -771,6 +771,8 @@ "MessageEvent", "MessagePort", "Navigator", + "PageRevealEvent", + "PageSwapEvent", "PageTransitionEvent", "Plugin", "PluginArray", @@ -1040,6 +1042,7 @@ "interfaces": [ "NavigateEvent", "Navigation", + "NavigationActivation", "NavigationCurrentEntryChangeEvent", "NavigationDestination", "NavigationHistoryEntry", @@ -1740,10 +1743,11 @@ }, "View Transitions API": { "overview": ["View Transitions API"], + "guides": ["/docs/Web/API/View_Transitions_API/Using"], "interfaces": ["ViewTransition"], "methods": ["Document.startViewTransition()"], "properties": [], - "events": [] + "events": ["Window: pagereveal", "Window: pageswap"] }, "VirtualKeyboard API": { "overview": ["VirtualKeyboard API"],