1. Introduction
This section is non-normative.
View Transitions is a set of API that allow DOM changes to smoothly animate between states. This is accomplished by leveraging user-agents ability to persist visual representations of state (i.e. snapshots) and blend them with current DOM state’s visual output. The API also allows the animations to be customized via standard CSS animation properties.
This spec describes the CSS and JS mechanics of the single-page transition API.
2. Transitions as an enhancement
This section is non-normative.
A key part of this API design is the view that an animated transition is an enhancement to a DOM change. Specifically, there are two components of the API: the DOM change, and the visual state animation.
In order for the user-agent to generate a set of snapshots prior to the DOM change, the API is designed to take the DOM change callback as part of the request to initiate a transition. This means that the user-agent has an opportunity to generate snapshots for the existing visual representation, run the given callback to update the state, and finally generate structures and set up animations required for the transition to occur. All this is accomplished with a single call to the JavaScript API.
The user-agent provides additional JavaScript functionality and promises to control and observe the state of the animations.
These are described in detail in the ViewTransition
section.
After the callback has finished running, the user-agent creates a structure of pseudo-elements that represent both the "old" and "new" states of the transition. The structure of the pseudo-elements is dictated by the view-transition-name property. Specifically, each element that is named with a view-transition-name creates a separate snapshot and thus a separate group of pseudo-elements that are animated independently from the rest. Note that for convenience, the document element is given the view-transition-name "root" in the user-agent style sheet.
The groups induced by the view-transition-name are all positioned within a common pseudo-element root, which itself is attached to the document element of the page.
Each of the groups is comprised of up to four pseudo elements:
- Group
-
This element initially mirrors the size and position of the "old" element that it represents (i.e. the transition-named element that caused this group to be created). The element is animated to the "new" size and position.
- Image-Pair
-
This element is a child of the group element and provides isolation: isolate for its children. It’s needed so that its children can be blended with non-normal blend modes without affecting other visual outputs.
- Old image
-
This element is a child of the image-pair element. It is a replaced element that produced the visual representation of the "old" state taken from user-agent provided snapshots. Note that the contents of this element can be manipulated with
object-*
properties in the same way that other replaced elements can be. - New image
-
This element is a child of the image-pair element. It is a replaced element that produces the visual representation of the "new" state, taken from the page’s visual output of the represented elements. Like the old image, the contents can be manipulated with
object-*
properties. Note that because this element’s snapshots are taken from the pages output, the visual output changes if the visual output of the represented element changes. This is similar to element(), although it differs in terms of the captured area.
This sections can benefit from diagrams.
Each of the pseudo-elements generated can be targeted by CSS in order to customize its appearance, behavior and/or add animations. This enables full customization of the transition.
Note that because these APIs are an enhancement to the DOM change, some principles emerge:
-
If a transition cannot run, or is skipped, the DOM change should still happen. If the DOM change should also be skipped, then that should be handled by another feature. The
NavigateEvent
is an example of a feature developers could use to handle this. -
Although the transition API allows DOM changes to be asynchronous via the
startViewTransition()
callback
, the transition API is not responsible for queuing or otherwise scheduling the DOM changes, beyond the scheduling needed for the transition itself. Some asynchronous DOM changes can happen concurrently (e.g if they’re happening within independent components), whereas others need to queue, or abort an earlier change. This is best left to a feature or framework that has a more holistic view of the update.
3. CSS properties
3.1. view-transition-name
Name: | view-transition-name |
---|---|
Value: | none <custom-ident> |
Initial: | none |
Applies to: | all elements |
Inherited: | no |
Percentages: | n/a |
Computed value: | as specified |
Canonical order: | per grammar |
Animation type: | discrete |
The view-transition-name property "names" an element as participating in a view transition.
- none
-
The element will not participate in a view transition.
- <custom-ident>
-
The element can participate in a view transition, as either an old or new element, with a view transition name equal to the <custom-ident>'s value.
Note: The value none is invalid as a <custom-ident>.
The document element participates in a view transition by default using the following rule, added to the HTML user agent style sheet:
html{ view-transition-name : root; }
Note: This property causes the user-agent to both capture separate snapshots from the elements, as well as create separate pseudo-element sub-trees representing this element’s "old" and "new" states. For the purposes of this API, if one element has a transition-name "foo" in the old state, and another element has a transition-name "foo" in the new state, they are treated as representing different visual state of the same element. This may be confusing, since the elements themselves are not necessarily referring to the same object, but it is a useful model to consider them to be visual states of the same conceptual page entity, that we happen to call "element".
4. User-agent keyframes
The following HTML user agent style sheet:
@keyframes -ua-view-transition-fade-out{ to{ opacity : 0 ; } } @keyframes -ua-view-transition-fade-in{ from{ opacity : 0 ; } }
5. Pseudo-elements
The following view-transition pseudo-elements represent the various items being animated.
The ::view-transition pseudo-element acts as a grouping element for other view-transition pseudo-elements and has the document’s originating element.
Note: For example, :root::view-transition selector matches this pseudo-element, but div::view-transition does not.
Other view-transition pseudo-elements take a <pt-name-selector> argument to specify which elements named with view-transition-name are affected.
There can be multiple pseudo-elements of the same type, one for each view-transition-name participating in a transition.
The <pt-name-selector> is defined as follows:
<pt-name-selector> = '*' <custom-ident>
A value of * makes the corresponding selector apply to all pseudo elements of the specified type. The specificity of a view-transition selector with a * argument is zero.
The <custom-ident> value makes the corresponding selector apply to exactly one pseudo element of the specified type, namely the pseudo-element that is created as a result of the view-transition-name property on an element with the same <custom-ident> value. The specificity of a view-transition selector with a <custom-ident> argument is the same as for other pseudo-elements, and is equivalent to a type selector.
The following describes all of the view-transition pseudo-elements and their function:
- ::view-transition
-
This pseudo-element is the grouping container of all the other view-transition pseudo-elements. Its document element.
The following is added to the HTML user agent style sheet:
html : :view-transition{ position : fixed; inset : 0 ; } Note: This pseudo-element provides a containing block for all ::view-transition-group() pseudo-elements. The aim of the style is to size the pseudo-element to cover the snapshot viewport and position all ::view-transition-group() pseudo-elements relative to the snapshot viewport origin.
- ::view-transition-group( <pt-name-selector> )
-
One of these pseudo-elements exists for each view-transition-name in a view transition, and holds the rest of the pseudo-elements corresponding to this view-transition-name.
Its originating element is the ::view-transition pseudo-element.
The following is added to the HTML user agent style sheet:
html : :view-transition-group ( *) { position : absolute; top : 0 ; left : 0 ; animation-duration : 0.25 s ; animation-fill-mode : both; } The aim of the style is to position the element relative to its ::view-transition parent.In addition to above, styles in the view transition style sheet animate this pseudo-element’s border box to that of the new element’s border box. Also the element’s transform is animated from the old element’s screen space transform to the new element’s screen space transform. This style is generated dynamically since the values of animated properties are determined at the time that the transition begins.
The selector for this and subsequently defined pseudo-elements is likely to change to indicate position in the pseudo-tree hierarchy.
- ::view-transition-image-pair( <pt-name-selector> )
-
One of these pseudo-elements exists for each view-transition-name being in a view transition, and holds the images of the old and new elements.
Its originating element is the ::view-transition-group() pseudo-element with the same transition-name.
The following is added to the HTML user agent style sheet:
html : :view-transition-image-pair ( *) { position : absolute; inset : 0 ; animation-duration : inherit; animation-fill-mode : inherit; } Note: The aim of the style is to position the element to occupy the same space as its ::view-transition-group() element.
- ::view-transition-old( <pt-name-selector> )
-
One of these pseudo-elements exists for each element in the old DOM being animated by the view transition, and is a replaced element displaying the old element’s snapshot image. It has natural dimensions equal to the snapshot’s size.
Its originating element is the ::view-transition-image-pair() pseudo-element with the same transition-name.
The following is added to the HTML user agent style sheet:
html : :view-transition-old ( *) { position : absolute; inset-block-start : 0 ; inline-size : 100 % ; block-size : auto; animation-duration : inherit; animation-fill-mode : inherit; } Note: The aim of the style is to match the element’s inline size while retaining the aspect ratio. It is also placed at the block start.
Note: Additional styles in the view transition style sheet added to animate these pseudo-elements are detailed in setup transition pseudo-elements and update pseudo-element styles.
- ::view-transition-new( <pt-name-selector> )
-
Identical to ::view-transition-old(), except it deals with the new element instead.
The precise tree structure, and in particular the order of sibling pseudo-elements, is defined in the setup transition pseudo-elements algorithm.
6. Concepts
6.1. Phases
Phases represent an ordered sequence of states. Since phases are ordered, prose can refer to phases before a particular phase, meaning they appear earlier in the sequence, or after a particular phase, meaning they appear later in the sequence.
The initial phase is the first item in the sequence.
Note: For the most part, a developer using this API does not need to worry about the different phases, since they progress automatically. It is, however, important to understand what steps happen in each of the phases: when the snapshots are captured, when pseudo-element DOM is created, etc. The description of the phases below tries to be as precise as possible, with an intent to provide an unambiguous set of steps for implementors to follow in order to produce a spec-compliant implementation.
6.2. The snapshot viewport
The snapshot viewport covers all areas of the window that could potentially display web content. This area is consistent regardless of root scrollbars or interactive widgets.
"Interactive widgets" refers to UI described within a property definition in CSS Viewport § 3.4 interactive-widget. This should be extracted into an exported definition that can be used independently of the property.
This means the snapshot canvas size is likely to be consistent for the document element's old image and new element.
The snapshot viewport origin refers to the start of the block and inline axes of the snapshot viewport.
6.3. The view-transition layer stacking layer
This specification introduces a stacking layer to the CSS 2 § Elaborate description of Stacking Contexts.
The ::view-transition pseudo-element generates a new stacking context called the view-transition layer with the following characteristics:
-
Its parent stacking context is the root stacking context.
-
If the ::view-transition pseudo-element exists, a new stacking context is created for the top layer. The view-transition layer is a sibling of this stacking context.
-
The view-transition layer paints after the stacking context for the top layer.
-
The view-transition layer is positioned at the snapshot viewport origin, and is the same size as the snapshot viewport. As in, it covers the snapshot viewport.
Note: The intent of the feature is to be able to capture the contents of the page, which includes the top layer elements. In order to accomplish that, the view-transition layer cannot be a part of the captured top layer context, since that results in a circular dependency. Instead, this stacking context is a sibling of other page contents.
Create a diagram to explain these stacking contexts.
Do we need to clarify that the stacking context for the root and top layer elements has filters and effects coming from the document element's style?
6.4. Captured elements
A captured element is a struct with the following:
- old image
-
an image or null. Initially null.
- old styles
-
a set of styles or null. Initially null.
The type of "a set of styles" needs to be linked or defined.
- new element
-
an element or null. Initially null.
In addition, a captured element has the following style definitions:
- group keyframes
-
A
CSSKeyframesRule
or null. Initially null. - group animation name rule
-
A
CSSStyleRule
or null. Initially null. - group styles rule
-
A
CSSStyleRule
or null. Initially null. - old view-box rule
-
A
CSSStyleRule
or null. Initially null. - new view-box rule
-
A
CSSStyleRule
or null. Initially null. - image pair isolation rule
-
A
CSSStyleRule
or null. Initially null. - view blend mode rule
-
A
CSSStyleRule
or null. Initially null.
Note: These are used to update, and later remove styles from a document's view transition style sheet.
6.5. Additions to Document
A Document
additionally has:
- active DOM transition
-
a
ViewTransition
or null. Initially null. - transition suppressing rendering
-
a boolean. Initially false.
- view transition style sheet
-
a style sheet. Initially a new style sheet in the HTML user agent style sheet.
Note: This is used to hold dynamic styles relating to transitions.
7. API
7.1. Additions to Document
partial interface Document {ViewTransition startViewTransition (optional UpdateDOMCallback ?=
callback null ); };callback =
UpdateDOMCallback any > ();
7.1.1. startViewTransition()
startViewTransition(callback)
are as follows:
-
Let transition be a new
ViewTransition
object in relevant Realm. -
Set transition’s DOM update callback to callback.
-
Let document be associated document.
-
If document’s active DOM transition is not null, then skip the view transition document’s active DOM transition with an "
relevant Realm.
Note: This can result in two asynchronous DOM update callbacks running concurrently. One for the document’s current active DOM transition, and another for this transition. As per the design of this feature, it’s assumed that the developer is using another feature or framework to correctly schedule these DOM changes.
-
Set document’s active DOM transition to transition.
Note: The process continues in setup view transition, via perform pending transition operations, which is called in § 8.1 Monkey patches to rendering.
-
Return transition.
document. startViewTransition( async () => { await coolFramework. changeTheDOMToPageB(); });
If more precise management is needed, however, transition elements can be managed in script:
async function doTransition() { / Specify "old" elements. The name is used to match against / "new" elements they should transition to, and to refer to / the transitioning pseudo-element. document. querySelector( ".old-message" ). style. viewTransitionName= "message" ; const transition= document. startViewTransition( async () => { / This callback is invoked by the browser when "old" / capture finishes and the DOM can be switched to the new / state. No frames are rendered until this callback returns. / DOM changes may be asynchronous await coolFramework. changeTheDOMToPageB(); / Naming elements during the callback marks them as / "new", to be matched up with the same-named "old" / elements marked previously and transitioned between. document. querySelector( ".new-message" ). style. viewTransitionName= "message" ; / viewTransitionNames must be unique, so the above assumes that / <code data-opaque bs-autolink-syntax='`.old-message`'>.old-message</code> has been removed/hidden by <code data-opaque bs-autolink-syntax='`changeTheDOMToPageB()`'>changeTheDOMToPageB()</code>. }); / When ready resolves, all pseudo-elements for this transition have / been generated. / They can now be accessed in script to set up custom animations. await transition. ready; document. documentElement. animate( keyframes, { ... animationOptions, pseudoElement: "::view-transition-group(message)" , }); / When the finished promise resolves, that means the transition is / finished. await transition. finished; }
7.2. The ViewTransition
interface
[Exposed =Window ]interface {
ViewTransition undefined skipTransition ();readonly attribute undefined >;
finished readonly attribute undefined >;
ready readonly attribute undefined >; };
domUpdated
Note: The ViewTransition
represents and controls a single same-document transition.
That is, it controls a transition where the starting and ending document are the same,
possibly with changes to the document’s DOM structure.
A ViewTransition
has the following:
- named elements
-
a map, whose keys are view transition names and whose values are captured elements. Initially a new map.
- phase
-
One of the following phases:
-
"
pending-capture
". -
"
dom-update-callback-called
". -
"
animating
". -
"
done
".
-
- DOM update callback
-
an
UpdateDOMCallback
or null. Initially null. - ready promise
-
a
Promise
. Initially relevant Realm. - DOM updated promise
-
a
Promise
. Initially relevant Realm. - finished promise
-
a
Promise
. Initially relevant Realm.
The finished
this’s finished promise.
The ready
this’s ready promise.
The domUpdated
this’s DOM updated promise.
7.2.1. skipTransition()
skipTransition()
are:
-
If this's phase is not "
done
", then skip the view transition for this with an "DOMException
.
8. Algorithms
8.1. Monkey patches to rendering
-
For each Document.
Note: These steps will be added to the update the rendering in the HTML spec. As such, the prose style is written to match other steps in that algorithm.
-
For each
Document
in docs with a transition suppressing rendering of true:Move this to the html spec. See html/8368.
How should input be handled when in this state? The last frame presented to the user will not reflect the DOM state as it asynchronously switches to the new version. See issue 7797.
Note: The aim is to prevent unintended DOM updates from being presented to the user after a cached snapshot for the elements has been captured. We wait for one rendering opportunity after prepare to present DOM mutations made by the author before prepare to be presented to the user. This is also the content captured in snapshots.
Note: These steps will be added to the update the rendering in the HTML spec. As such, the prose style is written to match other steps in that algorithm.
8.2. Perform pending transition operations
Document
document, perform the following steps:
-
If document’s active DOM transition is not null, then:
-
If document’s active DOM transition's phase is "
pending-capture
", then setup view transition with document’s active DOM transition. -
Otherwise, if document’s active DOM transition's phase is "
animating
", then update transition DOM for document’s active DOM transition.
-
8.3. Setup view transition
ViewTransition
transition,
perform the following steps:
-
Let namedElements be transition’s named elements.
-
Let usedTransitionNames be a new set of strings.
-
Let document be transition’s associated document.
-
pseudo-element connected to document, in paint order:
The link for "paint order" doesn’t seem right. Is there a more canonical definition?
-
If any continue.
-
Let transitionName be the computed value of view-transition-name for element.
-
If transitionName is none, or element is not rendered, then continue.
-
If any of the following is true:
-
usedTransitionNames contains transitionName.
-
element is not element’s layout containment.
-
element is not element’s fragmentation.
Then skip the view transition for transition with an "
relevant Realm, and return.
-
-
Append transitionName to usedTransitionNames.
-
Let capture be a new captured element struct.
-
Set capture’s old image to the result of capturing the image of element.
-
Set capture’s old styles to the following:
- transform
-
A CSS transform that would place element from the snapshot viewport origin to its current quad.
This value is identity for the document element.
- width
- height
-
The size of the snapshot viewport if element is the document element, otherwise, the width and height of element’s border box.
- object-view-box
-
document element, otherwise, an object-view-box value that, when applied to the old image, will cause the view box to coincide with element’s border box in the image. This must be expressed using inset().
- writing-mode
-
The writing-mode of element.
- direction
-
The direction of element.
-
Set namedElements[transitionName] to capture.
-
-
Set document’s transition suppressing rendering to true.
-
Queue a global task on the DOM manipulation task source, given transition’s relevant global object, to execute the following steps:
Note: A task is queued here because the texture read back in capturing the image may be async, although the render steps in the HTML spec act as if it’s synchronous.
"DOM manipulation task source" doesn’t link due to a bikeshed bug.
-
If transition’s phase is "
done
", then abort these steps.Note: This happens if transition was skipped before this point.
-
Call the DOM update callback of transition.
-
React to transition’s DOM updated promise:
-
If the promise does not settle within an implementation-defined timeout, then:
-
If transition’s phase is "
done
", then return.Note: This happens if transition was skipped before this point.
-
skip the view transition transition with a "
DOMException
.
-
-
If the promise was resolved, then:
-
If transition’s phase is "
done
", then return.Note: This happens if transition was skipped before this point.
-
Set transition suppressing rendering to false.
-
Let usedTransitionNames be a new set of strings.
-
pseudo-element connected to document, in paint order:
The link for "paint order" doesn’t seem right. Is there a more canonical definition?
-
If any continue.
-
Let transitionName be the computed value of view-transition-name for element.
-
If transitionName is none, or element is not rendered, then continue.
-
If any of the following is true:
-
usedTransitionNames contains transitionName.
-
element is not element’s layout containment.
-
element is not element’s fragmentation.
Then skip the view transition transition with an "
DOMException
, and return. -
-
Append transitionName to usedTransitionNames.
-
If namedElements[transitionName] does not exist, then set namedElements[transitionName] to a new captured element struct.
-
Let capture be namedElements[transitionName].
-
Let capture’s new element item be element.
-
-
Setup transition pseudo-elements for transition.
-
Update pseudo-element styles for transition.
Note: The above steps will require running document lifecycle phases, to compute information calculated during style/layout.
-
Set transition’s phase to "
animating
". -
Resolve transition’s ready promise.
-
-
If the promise was rejected with reason reason, then:
-
If transition’s phase is "
done
", then return.Note: This happens if transition was skipped before this point.
-
Skip the view transition transition with reason.
-
-
-
8.4. Skip the view transition
ViewTransition
transition with reason reason:
-
Let document be transition’s associated document.
-
Assert: document’s active DOM transition is transition.
-
If transition’s phase is before "
dom-update-callback-called
", then call the DOM update callback of transition. -
Set transition suppressing rendering to false.
-
If transition’s phase is equal to or after "
animating
", then clear view transition transition. -
Set transition’s phase to "
done
". -
Set document’s active DOM transition to null.
-
If transition’s ready promise has not yet been resolved, reject it with reason.
Note: The ready promise would’ve been resolved if
skipTransition()
is called after we start animating. -
React to transition’s DOM updated promise:
-
If transition’s DOM updated promise was resolved, then resolve transition’s finished promise.
-
If transition’s DOM updated promise was rejected with reason reason, then reject transition’s finished promise with reason.
-
8.5. Capture the image
Element
element, perform the following steps.
They return an image.
-
If element is the document element, then:
-
Render the region of the element and the top layer that intersects the snapshot viewport, on a transparent canvas the size of the snapshot viewport, following the capture rendering characteristics, and these additional characteristics:
-
Areas outside element’s scrolling box should be rendered as if they were scrolled to, without moving or resizing the layout viewport. This must not trigger events related to scrolling or resizing, such as
IntersectionObserver
s."scrolling box" and "layout viewport" are not exported. They either need exporting, or replaced with better references.
An example of what the user sees compared to the captured snapshot. This example assumes the root is the only element with a transition name. -
Areas that cannot be scrolled to (i.e. they are out of scrolling bounds), should render the canvas background.
An example of what the user sees compared to the captured snapshot. This example assumes the root is the only element with a transition name.
-
-
Return the canvas as an image. The natural size of the image is equal to the snapshot viewport.
-
-
Otherwise:
-
Render element and its descendants, at the same size it appears in its node document, over an infinite transparent canvas, following the capture rendering characteristics.
-
Let interestRectangle be the result of computing the interest rectangle for element.
Note: The interestRectangle is the subset of element’s ink overflow rectangle that should be captured. This is required for cases where an element’s ink overflow rectangle needs to be clipped because of hardware constraints. For example, if it exceeds the maximum texture size.
-
Return the portion of the canvas within interestRectangle as an image. The natural size of the image is equal to the interestRectangle bounds.
-
-
The origin of element’s ink overflow rectangle is anchored to canvas origin.
-
If the referenced element has a transform applied to it (or its ancestors), then the transform is ignored.
Note: This transform is applied to the snapshot using the
transform
property of the associated ::view-transition-group pseudo-element. -
Effects on the element, such as filter are applied to the capture.
-
pseudo-element of element, if descendant has a computed value of view-transition-name that is not none, then skip painting descendant.
Note: This is necessary since the descendant will generate its own snapshot which will be displayed and animated independently.
Refactor this so the algorithm takes a set of elements that will be captured. This centralizes the logic for deciding if an element should be included or not.
Specify what happens with mix-blend-mode.
8.6. Update transition DOM
ViewTransition
transition:
-
Let document be transition’s associated document.
-
Let hasActiveAnimations be a boolean, initially false.
-
For each view-transition pseudo-elements associated with transition:
-
Let element be the view-transition pseudo-element.
-
For each animation whose document timeline associated with document, and contains at least one effect target is element, set hasActiveAnimations to true if any of the following conditions is true:
The prose around "effect target" is incorrect, but #8001 needs to land before it can be fixed.
-
animation’s running.
-
document’s pending animation event queue has any events associated with animation.
This prose isn’t quite right, but it’s blocked on #8004.
-
-
-
If hasActiveAnimations is false:
-
Set transition’s phase to "
done
". -
Clear view transition transition.
-
Set document’s active DOM transition to null.
-
Resolve transition’s finished promise.
-
Return.
-
-
Update pseudo-element styles for transition.
Note: The above implies that a change in incoming element’s size or position will cause a new keyframe to be generated. This can cause a visual jump. We could retarget smoothly but don’t have a use-case to justify the complexity. See issue 7813 for details.
8.7. Compute the interest rectangle
Element
element, perform the following steps.
They return a rectangle.
-
Assert: element is not element’s document element.
Note: The document element is captured differently, as specified in capture the image.
-
If element’s ink overflow area does not exceed an implementation-defined maximum size, then return a rectangle that is equal to element’s ink overflow rectangle.
-
Otherwise:
Define the algorithm used to clip the snapshot when it exceeds max size.
8.8. Setup transition pseudo-elements
ViewTransition
transition:
-
Let document be associated document.
-
Let transitionRoot be the result of creating a new ::view-transition pseudo-element in document’s snapshot viewport.
-
For each transitionName → capturedElement of transition’s named elements:
-
Let group be the result of creating a new ::view-transition-group() pseudo-element with the name transitionName.
-
Append group to transitionRoot.
This should be better defined. I’m not sure if pseudo-elements have defined ways to modify their DOM.
-
Let imagePair be a new ::view-transition-image-pair() pseudo-element with the name transitionName.
-
Append imagePair to group.
-
If capturedElement’s old image is not null, then:
-
Let old be a new ::view-transition-old() replaced element pseudo-element, with the name transitionName, displaying capturedElement’s old image.
-
Append old to imagePair.
-
Let oldViewBox be capturedElement’s old styles object-view-box property.
-
Set capturedElement’s old view-box rule to a new
CSSStyleRule
representing the following CSS, and append it to document’s view transition style sheet.html : :view-transition-old ( transitionName) { object-view-box : oldViewBox; } Note: The above code example contains variables to be replaced.
-
-
If capturedElement’s new element is not null, then:
-
Let new be a new ::view-transition-new() replaced element pseudo-element, with the name transitionName, displaying the capture the image of capturedElement’s new element.
-
Append new to imagePair.
The new element and its contents (the flat tree descendants of the element, including both text and elements, or the replaced content of a replaced element), except the view-transition pseudo-elements, are not painted (as if they had visibility: hidden) and do not respond to hit-testing (as if they had pointer-events: none) until new exists.
-
-
If both of capturedElement’s old image and new element are not null, then:
-
Let transform be capturedElement’s old styles's transform property.
-
Let width be capturedElement’s old styles's width property.
-
Let height be capturedElement’s old styles's height property.
-
Set capturedElement’s group keyframes to a new
CSSKeyframesRule
representing the following CSS, and append it to document’s view transition style sheet:@keyframes -ua-view-transition-group-anim-transitionName{ from{ transform : transform; width : width; height : height; } } Note: The above code example contains variables to be replaced.
-
Set capturedElement’s group animation name rule to a new
CSSStyleRule
representing the following CSS, and append it to document’s view transition style sheet:html : :view-transition-group ( transitionName) { animation-name : -ua-view-transition-group-anim-transitionName; } Note: The above code example contains variables to be replaced.
-
Set capturedElement’s image pair isolation rule to a new
CSSStyleRule
representing the following CSS, and append it to document’s view transition style sheet:html : :view-transition-image-pair ( transitionName) { isolation : isolate; } Note: The above code example contains variables to be replaced.
-
Set capturedElement’s view blend mode rule to a new
CSSStyleRule
representing the following CSS, and append it to document’s view transition style sheet:html : :view-transition-old ( transitionName), html::view-transition-new ( transitionName) { mix-blend-mode : plus-lighter; } Note: The above code example contains variables to be replaced.
Note: mix-blend-mode: plus-lighter ensures that the blending of identical pixels from the old and new images results in the same color value as those pixels, and achieves a "correct" cross-fade.
Isolation and the dynamic setting of blending is only necessary to get the right cross-fade between new and old image pixels. Would it be simpler to always add it and try to optimize in the implementation?
-
-
8.9. Update pseudo-element styles
ViewTransition
transition:
-
For each transitionName → capturedElement of transition’s named elements:
-
Let width, height, transform, writingMode, and direction be null.
-
If capturedElement’s new element is null, then:
-
Set width to capturedElement’s old styles width property.
-
Set height to capturedElement’s old styles height property.
-
Set transform to capturedElement’s old styles transform property.
-
Set writingMode to capturedElement’s old styles writing-mode property.
-
Set direction to capturedElement’s old styles direction property.
-
-
Otherwise:
-
Set width to the current width of capturedElement’s new element's border box.
-
Set height to the current height of capturedElement’s new element's border box.
-
Set transform to a transform that maps the capturedElement’s new element's border box from document origin to its quad from the snapshot viewport origin.
-
Set writingMode to the writing-mode on capturedElement’s new element.
-
Set direction to the direction on capturedElement’s new element.
-
-
If capturedElement’s group styles rule is null, then set capturedElement’s group styles rule to a new
CSSStyleRule
representing the following CSS, and append it to document’s view transition style sheet.Otherwise, update capturedElement’s group styles rule to match the following CSS:
html : :view-transition-group ( transitionName) { width : width; height : height; transform : transform; writing-mode : writingMode; direction : direction; } Note: The above code example contains variables to be replaced.
-
If capturedElement’s new element is not null, then:
-
Let new be the ::view-transition-new() replaced element pseudo-element, with the name transitionName, displaying the capture the image of capturedElement’s new element.
-
Let newViewBox be an object-view-box value that when applied to new, will cause the view box to coincide with capturedElement’s new element's border box in the image. This must be expressed using inset().
-
If capturedElement’s new view-box rule is null, then set capturedElement’s new view-box rule to a new
CSSStyleRule
representing the following CSS, and append it to document’s view transition style sheet.Otherwise, update capturedElement’s new view-box rule to match the following CSS:
html : :view-transition-new ( transitionName) { object-view-box : newViewBox; } Note: The above code example contains variables to be replaced.
-
-
This algorithm must be executed to update styles in user-agent origin if its effects can be observed by a web API.
Note: An example of such a web API is window.getComputedStyle(document.documentElement, "::view-transition")
.
ViewTransition
transition:
-
Assert: transition’s phase is before "
dom-update-callback-called
". -
Let callbackPromise be relevant Realm.
-
If transition’s DOM update callback is null, then resolve callbackPromise.
-
Otherwise, let callbackPromise be the result of invoking transition’s DOM update callback.
-
-
Set transition’s phase to "
dom-update-callback-called
". -
React to callbackPromise:
-
If callbackPromise was resolved, then resolve transition’s DOM updated promise.
-
If callbackPromise was rejected with reason r, then reject transition’s DOM updated promise with r.
-
8.10. Clear view transition
ViewTransition
transition:
-
Let document be transition’s associated document.
-
Remove all associated view-transition pseudo-elements from document.
-
-
For each style of capturedElement’s style definitions:
-
If style is not null, then remove style from document’s view transition style sheet.
-
-
Privacy Considerations
This specification introduces no new privacy considerations.
Security Considerations
The images generated using capture the image algorithm could contain cross-origin data (if the Document is embedding cross-origin resources) or sensitive information like visited links. The implementations must ensure this data can not be accessed by the Document. This should be feasible since access to this data should already be prevented in the default rendering of the Document.