1. Introduction
This section is non-normative.
View Transitions, as specified in [css-view-transitions-1], is a feature that allows developers to create animated transitions between visual states of the document.
Level 2 extends that specification, by adding the necessary API and lifecycle to enable transitions across a same-origin cross-document navigation.
1.1. Lifecycle
This section is non-normative.
A successful cross-document view transition goes through the following phases:
-
The user navigates, by clicking a link, submitting a form, traversing history using the browser UI, etc.
-
Once it’s time to unload the old document, if the navigation is same origin and the old
Document
has opted in to cross-document view-transitions, the old state is captured. -
An event named
reveal
is fired on the newDocument
, with aviewTransition
property, which is aViewTransition
object. ThisViewTransition
's
is already resolved, and its captured elements are populated from the oldupdateCallbackDone
Document
. -
Right before the new
Document
has the first rendering opportunity, its state is captured as the "new" state. -
From this point forward, the transition continues as if it was a same-document transition, as per activate view transition.
1.2. Examples
Instead, we opt in to auto-view-transitions in both page 1 and page 2:
// in both documents:@auto-view-transitions { same-origin : enable; }
A link from page 1 to or from page 2 would generate a crossfade transition for example 1. To achieve the effect examples 2, 3 & 4, simply put the CSS for the pseudo-elements in both documents.
-
Opt-in to auto-view-transitions in both pages.
-
Pass the click location to the new document, e.g. via
sessionStorage
. -
Intercept the
ViewTransition
object in the new document, using thereveal event
.
In both pages:
@auto-view-transitions { same-origin : enable; }
In the old page:
addEventListener( 'click' , event=> { sessionStorage. setItem( "lastClickX" , event. clientX); sessionStorage. setItem( "lastClickY" , event. clientY); });
In the new page:
// This would run both on initial load and on reactivation from BFCache. addEventListener( "reveal" , async event=> { if ( ! event. viewTransition) return ; const x= sessionStorage. getItem( "lastClickX" ) ?? innerWidth/ 2 ; const y= sessionStorage. getItem( "lastClickY" ) ?? innerHeight/ 2 ; const endRadius= Math. hypot( Math. max( x, innerWidth- x), Math. max( y, innerHeight- y) ); await event. viewTransition. ready; // Animate the new document’s 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' , pseudoElement: '::view-transition-new(root)' } ); })
2. CSS rules
2.1. The @auto-view-transition rule
The @auto-view-transition rule is used by a document to indicate that cross-document navigations
should setup and activate a ViewTransition
. To take effect, it must be present in the old document
when unloading, and in the new document when it is being revealed.
2.2. @auto-view-transition rule grammar
@auto-view-transition rules are parsed according to the following grammar, plus the additional rules noted below:
@auto-view-transition = @auto-view-transition { <declaration-rule-list> }
2.3. The same-origin property
Name: | same-origin |
---|---|
For: | @auto-view-transition |
Value: | enabled | disabled |
Initial: | disabled |
The 'same-origin' property opts in to automatically performing a view transition when performing a same origin navigation. It needs to be enabled both in the old document (when unloading) and in the new document (when ready to render).
- disabled
-
There will be no transition.
- enabled
-
The transition will be enabled if the navigation is same-origin, without cross-origin redirects.
3. API
3.1. The PageRevealEvent
Note: this should go in the HTML spec. See Issue 9315.
[Exposed =Window ]interface PageRevealEvent :Event {readonly attribute ViewTransition ?viewTransition ; };
Note: this event is fired when revealing a document.
The viewTransition
getter steps are to return the inbound cross-document view-transition for this’s relevant global object’s associated document.
4. Algorithms
4.1. Data Structures
4.1.1. Additions to Document
A Document
additionally has:
- is revealed
-
a boolean, initially false.
- is inbound cross-document transition
-
a boolean, initially false.
-
For each fully active
Document
doc in docs, reveal doc. -
Set document’s is revealed to false.
-
If document’s is revealed is true, then return.
-
Let transition be the result of getting the inbound cross-document view-transition for document.
-
If transition is not null and document does not opt in to cross-document view transitions, then skip transition and set transition to null.
-
Fire a new event named
reveal
on document’s relevant global object, usingPageRevealEvent
. -
If transition is not null, then activate transition.
-
Set document’s is revealed to true.
-
If oldDocument’s origin is not same origin as newDocument’s origin then call onReady and return.
-
If newDocument was created via cross-origin redirects is true and newDocument’s latest entry is null, then call onReady and return.
Note: A document with a non-null latest entry is being reactivated, in which case we don’t need to check for cross-origin redirects.
-
If oldDocument does not opt in to cross-document view transitions, then call onReady and return.
Note: We don’t know yet if newDocument has opted in, as it might not be parsed yet. We check the opt-in for newDocument when it is revealed.
-
If oldDocument’s active view transition is not null, then skip oldDocument’s active view transition with an "
AbortError
"DOMException
in oldDocument’s relevant Realm.Note: this means that any running transition would be skipped when the document is ready to unload.
-
Let outboundTransition be a new
ViewTransition
object in oldDocument’s relevant Realm, whose process old state captured is set to the following steps:should we check for the opt-in again, in case there was a CSSOM change in a requestAnimationFrame callback?
-
If outboundTransition’s phase is "
done
", then call onReady and return. -
Assert: outboundTransition’s phase is "
pending-capture
". -
Clear view transition outboundTransition.
Note: The ViewTransition object on the old Document should be destroyed after its state has been copied to the new Document below. We explicitly clear it here since the old Document may be cached by the UA.
-
Queue a global task on the DOM manipulation task source given newDocument’s relevant global object, to perform the following step:
-
Let newDocument’s active view transition be a new
ViewTransition
in newDocument’s relevant Realm, whose named elements is outboundTransition’s named elements, initial snapshot containing block size is outboundTransition’s initial snapshot containing block size, and whose is inbound cross-document transition is true. -
Call the update callback for newDocument’s active view transition.
-
Call onReady.
-
Note: outboundTransition is not exposed to JavaScript, it is used only for capturing the state of the old document.
-
-
Set oldDocument’s active view transition to outboundTransition.
Note: The process continues in setup view transition, via perform pending transition operations, which is called in .
-
Let transition be document’s active view transition.
-
If transition is null or transition’s is inbound cross-document transition is false, then return null.
Note: transition’s is inbound cross-document transition would be false if a same-document transition was started before the page was revealed.
-
Return transition.
-
The cross-origin isolated capability in both documents might be different. This can cause a situation where a
Document
that is cross-origin isolated can read image data from a document that is not cross-origin isolated. This is already mitigated in [[css-view-transitions-1#sec], as the same restriction applies for captured cross-origin iframes. -
A same-origin navigation might still occur via a cross-origin redirect, e.g.
https://example.com
links tohttps://auth-provider.com/
which redirects back tohttps://example.com/loggedin
.This can cause a (minor) situation where the cross-origin party would redirect the user to an unexpected first-party URL, causing an unexpected transition and obfuscating that fact that there was a redirect. To mitigate this, currently view transitions are disabled for navigations if the
Document
was created via cross-origin redirects. Note that this check doesn’t apply when theDocument
is being reactivated, as in that case the cross-origin redirect has already taken place.Note: this only applies to server-side redirects. A client-side redirect, e.g. using [^meta/http-equiv/refresh^], is equivalent to a new navigation.
-
This feature exposes more information to CSS, as so far CSS was not aware of anything navigation-related. This can raise concerns around safety 3rd-party CSS. However, as a general rule, 3rd-party stylesheets should come from trusted sources to begin with, as CSS can learn about the document or change it in many ways.
4.1.2. Additions to ViewTransition
## {#view-transitions-extension}
A ViewTransition
additionally has:
4.2. Monkey patches to HTML
If changingNavigationContinuation update-only is false, then setup outbound cross-document view transition given oldDocument, newDocument and the remaining steps and return from these steps.
Note: This would wait until a transition is captured or skipped before proceeding to unloading the old document and activating the new one.
Document
document:
4.3. Setting up and activating the cross-document view transition
Document
oldDocument,
a Document
newDocument, and onReady, which is an algorithm accepting nothing:
Document
document:
Document
document is said to opt in to cross-document view transitions if the computed value of same-origin is enabled
. Privacy Considerations
This specification introduces no new privacy considerations.
Security Considerations
To prevent cross-origin issues, at this point cross-document view transitions can only be enabled for same-origin navigations. As discussed in WICG/view-transitions#200, this still presents two potential threats:
See Issue #8684 and WICG/view-transitions#200 for detailed discussion.