Last updated: First published:
View Transition JavaScript API
Browser-native cross-document view transitions can be created entirely with CSS, without the need for JavaScript. However, JavaScript becomes essential for advanced functionality, such as:
- Triggering same-page view transitions with
startViewTransition()
, - Dynamically modifying CSS properties like
view-transition-name
, - Defining view transition types,
- Executing code at the start or end of a transition.
Same-Document View Transitions
Same document view transitions are amazing! You assign view transition names to the HTML elements you want to animate during the transition. The transition spans from the current DOM state to a future version, which is generated by calling and awaiting an update function.
startViewTransition()
Typically, you start a same-document view transition with an update callback that transforms the current DOM to the future state. The View Transition API takes care of creating and running animations that smoothly transform the old state into the new one.
if (window.matchMedia('(prefers-reduced-motion: reduce)') || !document.startViewTransition) { updateCallback()} else { document.startViewTransition(updateCallback);}
For users who prefer reduced motion or when the browser doesn’t support the View Transition API, the code above directly executes the update function without calling startViewTransition()
.
The update callback can either be a synchronous or asynchronous function. If it’s asynchronous, the View Transition API will wait for it to settle. However, you should aim to spend only little time inside the callback. For one thing, the browser freezes the renderer while the update callback executes. And browsers may impose time limits. For Chrome this seem to be 4 seconds before it loses its temper. If you need an expensive preparation for the transition, like loading and parsing a new DOM from file, you better do that before you call startViewTransition()
. The update callback is optional, so you can even transition to the same version of the DOM by omitting the update function, which might make sense with custom animations.
You can also pass an options object to startViewTransition()
to define view transition types that should be active during the transition.
document.startViewTransition({ types: ["boom", "backward"], update: changeTheDOM,});
Here is the full signature for startViewTransition
type UpdateCallback = undefined | (() => void | Promise<void>);type StartViewTransitionOptions = { types?: string[] | Set<string>; update?: UpdateCallback;};
interface Document { startViewTransition( param?: StartViewTransitionOptions | UpdateCallback ): ViewTransition;}
ViewTransition Object
The startViewTransition()
function returns an object that includes promises, the current transition types, and a function to skip the animations.
interface ViewTransition { readonly updateCallbackDone: Promise<undefined>; readonly ready: Promise<undefined>; readonly finished: Promise<undefined>; readonly types: Set<string>; skipTransition(): void;}
Promises
The promises allow you to hook into the different stages of the view transition process.
-
The
updateCallbackDone
promise resolves once the update callback has finished. You can use this to (synchronously) make last-minute changes before the new images are created. If the promise rejects, view transition processing ends, and thefinished
promise also rejects. -
The
ready
promise settles once the pseudo-elements have been inserted into the DOM. Inserting the pseudo-elements triggers their animations. For example, you can use this promise to add your own JavaScript animations using the Web Animation API. If there are errors, like duplicate view transition names, theready
promise will reject. -
Lastly, the
finished
promise settles once the animations are complete and the pseudo-elements have been removed. It resolves with the same outcome asupdateCallbackDone
.
When using the promises, your call to startViewTransition()
might look something like this:
if (document.startViewTransition && window.matchMedia('(prefers-reduced-motion: no-preference)')) { const viewTransition = document.startViewTransition({update: updateCallback, types: ...}); viewTransition.updateCallbackDone.catch(err => ... error handling ...); viewTransition.ready.catch(err => ... error handling ...); viewTransition.ready.then(() => ... trigger parallel animation ...); viewTransition.finished.finally(() => ... clean up ...)} else { updateCallback();}
skipTransition()
Calling skipTransition()
stops the current view transition animations or prevents their start if the ready
promise hasn’t settled yet. If called during the update callback, it doesn’t affect the update itself, nor does it impact the processing or the outcome of the updateCallbackDone promise.
Types
You can dynamically add or remove view transition types during the view transition by modifying the types
object. Such changes will directly affect CSS rules that use the :active-view-transition-type
pseudo-class.
Canceling and Chaining
Calling startViewTransition()
while another view transition is active will interrupt the current view transition, fast forward to the end state of the animations, and start the new view transition from there.
Currently, browser behavior differs regarding the effects that occur when startViewTransition
is called before updateCallbackDone
resolves. You should better avoid this scenario. You can either chain the update callback functions and pass the chained callback to a single call of startViewTransition()
, or chain multiple calls to startViewTransition()
by awaiting the finished
promise before starting the next view transition.
Cross-Document View Transitions
Cross-document view transitions work similarly to same-document ones but are triggered by navigation. In particular you can get access to the view transition object in event listeners for the new pageswap
and pagereveal
events.
Pageswap and Pagereveal Events
Two key events enable JavaScript interaction: pageswap
, dispatched just before leaving the old page, and pagereveal
, dispatched before the new page renders.
ViewTransition Object
Both events include a viewTransition
property, which holds a ViewTransition
object if the transition is part of a cross-document view transition. The object has the same structure as for same-document view transitions.
For pageswap
, if viewTransition
is defined, its promises will never settle because the page is unloaded before it is “updated”.
For pagereveal
, if viewTransition
is defined, its updateCallbackDone
promise is immediately settled.
The events allow you to manipulate the DOM or CSS properties right before snapshots are taken or the new page’s live images are captured. In particular, they allow for setting view transition types for the current view transition.
In a pageswap
listener, you can define view transition types by adding them to event.viewTransition.types
, which are then only applied to the old page. The types can be used to control via CSS what view transition names are defined on the old page. You can also directly modify view transition names in the listener as snapshots for the ::view-transition-old
pseudo elements are taken after this event is dispatched.
Similarly, pagereveal
listeners allow you to tweak view transition names and types for the new page. Again, live images for the ::view-transition-new
pseudo-elements are being captured after the event.
Activation Object
The pageswap
event also provides a NavigationActivation
object via its activation
property, offering details about the current page (from
) and next page (entry
). While the pagereveal
event does not include this property, in browsers supporting the Navigation API, you can use navigation.activation
to access information about the previous page (from
) and current page (entry
).