CSS View Transitions Module Level 2
CSS View Transitions Module Level 2
Editor’s Draft
9 March 2026
More details about this document
This version:
Latest published version:
Feedback:
CSSWG Issues Repository
Inline In Spec
Editors:
Noam Rosenthal
Google
Khushal Sagar
Google
Vladimir Levin
Google
Tab Atkins-Bittner
Google
Suggest an Edit for this Spec:
GitHub Editor
World Wide Web Consortium
W3C
liability
trademark
and
permissive document license
rules apply.
Abstract
This module defines the View Transition API, along with associated properties and pseudo-elements,
which allows developers to create animated visual transitions representing changes in the document state.
CSS
is a language for describing the rendering of structured documents
(such as HTML and XML)
on screen, on paper, etc.
Status of this document
This is a public copy of the editors’ draft.
It is provided for discussion only and may change at any moment.
Its publication here does not imply endorsement of its contents by W3C.
Don’t cite this document other than as work in progress.
Please send feedback
by
filing issues in GitHub
(preferred),
including the spec code “css-view-transitions” in the title, like this:
“[css-view-transitions]
…summary of comment…
”.
All issues and comments are
archived
Alternately, feedback can be sent to the (
archived
) public mailing list
www-style@w3.org
This document is governed by the
18 August 2025 W3C Process Document
1.
Introduction
This section is non-normative.
This specification introduces a DOM API and associated CSS features
that allow developers to create animated visual transitions,
called
view transitions
between different states of a
document
or an
element
or between distinct same-origin documents.
1.1.
Level 2 Updates
Level 2 defines the following,
extending the model in
[CSS-VIEW-TRANSITIONS-1]
Cross-document view transitions
, including the
@view-transition
rule and the algorithms
that enable the cross-document view transition lifecycle.
Selective view transitions
, a way to match styles based on the existence of an
active view transition
and more specifically based on the active view transition being of a certain type.
Sharing styles between view transition pseudo-elements
, a way to declare a style once,
and use it for multiple view transition pseudo-elements. This includes the
view-transition-class
property, and
additions to named pseudo-elements
Nested view transition groups
, a way to construct deeper hierarchies of view transition pseudo-elements,
which in turn allows relative transforms and clipping of participating elements.
Scoped view transitions
, a way to perform view transitions within the scope of a DOM subtree.
1.2.
Separating Visual Transitions from DOM Updates
Traditionally, creating a visual transition between two document states
required a period where both states were present in the DOM at the same time.
In fact, it usually involved creating a specific DOM structure
that could represent both states.
For example, if one element was “moving” between containers,
that element often needed to exist outside of either container for the period of the transition,
to avoid clipping from either container or their ancestor elements.
This extra in-between state often resulted in UX and accessibility issues,
as the structure of the DOM was compromised for a purely-visual effect.
View Transitions
avoid this troublesome in-between state
by allowing the DOM to switch between states instantaneously,
then performing a customizable visual transition between the two states in another layer,
using a static visual capture of the old state, and a live capture of the new state.
These captures are represented as a tree of
pseudo-elements
(detailed in
§ 5.2 View Transition Pseudo-elements
),
where the old visual state co-exists with the new state,
allowing effects such as cross-fading
while animating from the old to new size and position.
1.3.
View Transition Customization
By default,
element.
startViewTransition()
and
document.
startViewTransition()
create a
view transition
consisting of a cross-fade of the entire
root element
between the two DOM states.
Developers can instead choose which descendant elements are captured independently
using the
view-transition-name
CSS property,
allowing these to be animated independently of the rest of the page.
Since the transitional state (where both old and new visual captures exist)
is represented as pseudo-elements,
developers can customize each transition using familiar features
such as
CSS Animations
and
Web Animations
1.4.
View Transition Lifecycle
A successful
view transition
goes through the following phases:
Developer calls
document.
startViewTransition
updateCallback
or
element.
startViewTransition
updateCallback
which returns a
ViewTransition
viewTransition
Current state is captured as the “old” state.
Rendering is paused within the view transition
root element
Developer’s
updateCallback
function, if provided, is called,
which updates the document state.
viewTransition
updateCallbackDone
fulfills.
Current state is captured as the “new” state.
Transition pseudo-elements are created.
See
§ 5.2 View Transition Pseudo-elements
for an overview of this structure.
Rendering is unpaused, revealing the transition pseudo-elements.
viewTransition
ready
fulfills.
Pseudo-elements animate until finished.
Transition pseudo-elements removed.
viewTransition
finished
fulfills.
The following set of diagrams demonstrate the transition phases that a view transition goes through while performing the above steps:
1.5.
Transitions as an enhancement
A key part of the View Transition API design
is that an animated transition is a visual
enhancement
to an underlying document state change.
That means a failure to create a visual transition,
which can happen due to misconfiguration or device constraints,
will not prevent the developer’s
ViewTransitionUpdateCallback
being called,
even if it’s known in advance that the transition animations cannot happen.
For example, if the developer calls
skipTransition()
at the start of the
view transition lifecycle
the steps relating to the animated transition,
such as creating the
view transition tree
will not happen.
However, the
ViewTransitionUpdateCallback
will still be called.
It’s only the visual transition that’s skipped,
not the underlying state change.
Note:
If the DOM change should also be skipped,
then that needs to be handled by another feature.
navigateEvent
signal
is an example of a feature developers could use to handle this.
Although the View Transition API allows DOM changes to be asynchronous via the
ViewTransitionUpdateCallback
the API is not responsible for queuing or otherwise scheduling DOM changes
beyond any 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. The callback execution order is only specified for
callbacks that result from view transitions on the same root element, or on elements related by DOM ancestors.
In general, the scheduling order is best left to a feature or framework that has a more holistic view of the application.
1.6.
Rendering Model
View Transition works by replicating an element’s rendered state using UA generated pseudo-elements.
Aspects of the element’s rendering which apply to the element itself or its descendants,
for example visual effects like
filter
or
opacity
and clipping from
overflow
or
clip-path
are applied when generating its image in
Capture the image
However, properties like
mix-blend-mode
which define how the element draws when it is embedded can’t be applied to its image.
Such properties are applied to the element’s corresponding
::view-transition-group()
pseudo-element,
which is meant to generate a box equivalent to the element.
If the
::view-transition-group()
has a corresponding element in the "new" states,
the browser keeps the properties copied over to the
::view-transition-group()
in sync with the DOM element in the "new" state.
If the
::view-transition-group()
has corresponding elements both in the "old" and "new" state,
and the property being copied is interpolatable,
the browser also sets up a default animation to animate the property smoothly.
1.7.
Examples
Taking a page that already updates its content using a pattern like this:
function
spaNavigate
data
updateTheDOMSomehow
data
);
view transition
could be added like this:
function
spaNavigate
data
// Fallback for browsers that don't support this API:
if
document
startViewTransition
updateTheDOMSomehow
data
);
return
// With a transition:
document
startViewTransition
(()
=>
updateTheDOMSomehow
data
));
This results in the default transition of a quick cross-fade:
The cross-fade is achieved using CSS animations on a
tree of pseudo-elements
so customizations can be made using CSS. For example:
::view-transition-old
root
),
::view-transition-new
root
animation-duration
This results in a slower transition:
Building on the previous example, motion can be added:
@keyframes
fade-in
from
opacity
@keyframes
fade-out
to
opacity
@keyframes
slide-from-right
from
transform
translateX
30
px
);
@keyframes
slide-to-left
to
transform
translateX
-30
px
);
::view-transition-old
root
animation
90
ms
cubic-bezier
0.4
both fade-out
300
ms
cubic-bezier
0.4
0.2
both slide-to-left
::view-transition-new
root
animation
210
ms
cubic-bezier
0.2
90
ms
both fade-in
300
ms
cubic-bezier
0.4
0.2
both slide-from-right
Here’s the result:
Building on the previous example,
the simple "whole document" transition displayed a visible judder in the purple heading bar,
and had the heading text always slide to the left
even when it was "moving" to the right in the 1->2 transition.
To fix these issues,
the header and text within the header can be given their own
view-transition-name
for the transition,
which creates a separate
::view-transition-group()
.main-header
view-transition-name
main-header
.main-header-text
view-transition-name
main-header-text
/* Give the element a consistent size, assuming identical text: */
width: fit-content
By default, these groups will transition size and position from their “old” to “new” state,
while their visual states cross-fade:
Building on the previous example, let’s say some pages have a sidebar:
In this case, things would look better if the sidebar was static if it was in both the “old” and “new” states.
Otherwise, it should animate in or out.
The
:only-child
pseudo-class can be used to create animations specifically for these states:
.sidebar
view-transition-name
sidebar
@keyframes
slide-to-right
to
transform
translateX
30
px
);
/* Entry transition */
::view-transition-new
sidebar
:only-child
animation
300
ms
cubic-bezier
0.2
both fade-in
300
ms
cubic-bezier
0.4
0.2
both slide-from-right
/* Exit transition */
::view-transition-old
sidebar
:only-child
animation
150
ms
cubic-bezier
0.4
both fade-out
300
ms
cubic-bezier
0.4
0.2
both slide-to-right
For cases where the sidebar has both an “old” and “new” state, the default animation is correct.
Not building from previous examples this time,
let’s say we wanted to create a circular reveal from the user’s cursor.
This can’t be done with CSS alone.
Firstly, in the CSS, allow the “old” and “new” states to layer on top of one another without the default blending,
and prevent the default cross-fade animation:
::view-transition-image-pair
root
isolation
auto
::view-transition-old
root
),
::view-transition-new
root
animation
none
mix-blend-mode
normal
Then, the JavaScript:
// 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
lastClick
clientX
??
innerWidth
const
lastClick
clientY
??
innerHeight
// Get the distance to the furthest corner
const
endRadius
Math
hypot
Math
max
innerWidth
),
Math
max
innerHeight
);
// 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
${
px
${
px)\`,
\`circle(
${
endRadius
px at
${
px
${
px)\`,
],
},
duration: 500,
easing: 'ease-in',
// Specify which pseudo-element to animate
pseudoElement: '::view-transition-new(root)',
);
});
And here’s the result:
2.
API
2.1.
Additions to
Document
partial
interface
Document
ViewTransition
startViewTransition
optional
ViewTransitionUpdateCallback
or
StartViewTransitionOptions
callbackOptions
= {}
);
readonly
attribute
ViewTransition
activeViewTransition
};
callback
ViewTransitionUpdateCallback
Promise
any
> ();
dictionary
StartViewTransitionOptions
ViewTransitionUpdateCallback
update
null
sequence
DOMString
>?
types
null
};
viewTransition
document
startViewTransition
updateCallback
Starts a new
view transition
(canceling the
document
’s existing
active view transition
, if any).
updateCallback
, if provided, is called asynchronously, once the current state of the document is captured.
Then, when the promise returned by
updateCallback
fulfills,
the new state of the document is captured
and the transition is initiated.
Note that
updateCallback
, if provided, is
always
called,
even if the transition cannot happen
(e.g. due to duplicate
view-transition-name
values).
The transition is an enhancement around the state change, so a failure to create a transition never prevents the state change.
See
§ 1.5 Transitions as an enhancement
for more details on this principle.
If the promise returned by
updateCallback
rejects, the transition is skipped.
2.1.1.
startViewTransition()
Method Steps
The
method steps
for
startViewTransition(
callbackOptions
are as follows:
Perform the
Element
startViewTransition()
method steps
given
callbackOptions
but for the
document root element
and return the result.
2.1.2.
activeViewTransition
Property
In order to provide ergonomic behavior,
the
active view transition
is exposed to script via a document property.
activeViewTransition
of type
ViewTransition
, readonly, nullable
Returns the
active view transition
for the
document
or null if there is no active view transition.
Note:
An
element.startViewTransition()
call does not update
document.activeViewTransition
, but will update
activeViewTransition
on the
element
2.2.
Additions to
Element
partial
interface
Element
ViewTransition
startViewTransition
optional
ViewTransitionUpdateCallback
or
StartViewTransitionOptions
callbackOptions
= {}
);
readonly
attribute
ViewTransition
activeViewTransition
};
viewTransition
el
startViewTransition
updateCallback
Starts a new
view transition
(potentially canceling a conflicting
view transition
).
updateCallback
, if provided, is called asynchronously, once the current state of the element and its subtree is captured.
Then, when the promise returned by
updateCallback
fulfills,
the new state of the element and its subtree is captured
and the transition is initiated.
Note that
updateCallback
, if provided, is
always
called,
even if the transition cannot happen
(e.g. due to duplicate
view-transition-name
values).
The transition is an enhancement around the state change, so a failure to create a transition never prevents the state change.
See
§ 1.5 Transitions as an enhancement
for more details on this principle.
If the promise returned by
updateCallback
rejects, the transition is skipped.
2.2.1.
startViewTransition()
Method Steps
The
method steps
for
startViewTransition(
callbackOptions
are as follows:
Let
document
be
this’s
relevant global object’s
associated document
Let
viewTransition
be a new
ViewTransition
object in
document
’s
relevant Realm
with
root element
set to
this
If
callbackOptions
is a
ViewTransitionUpdateCallback
set
viewTransition
’s
update callback
to
callbackOptions
Otherwise, if
callbackOptions
is a
StartViewTransitionOptions
, then set
viewTransition
’s
update callback
to
callbackOptions
’s
update
If
this
’s
principal box
is
not rendered
or is an
internal ruby box
or a
non-atomic
inline-level
box,
skip
viewTransition
with an "
InvalidStateError
DOMException
If
this
is not the
document root element
force
this
to have both
layout containment
and
view transition scoping
for the duration of the transition.
If
document
’s
active view transition
is not null and its
outbound post-capture steps
is not null,
then:
Skip
viewTransition
with an "
InvalidStateError
DOMException
Note:
The
viewTransition
’s
types
are ignored here because the transition is never activated.
Return
viewTransition
Note:
This ensures that a same-document transition that started after firing
pageswap
is skipped.
If
this
’s
active view transition
is not null,
then
skip that view transition
with an "
AbortError
DOMException
in
this’s
relevant Realm
Note:
This can result in two asynchronous
update callbacks
running concurrently
(and therefore possibly out of sequence):
one for the
this
’s current
active view transition
, and another for this
viewTransition
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
this
’s
active view transition
to
viewTransition
Note:
The
view transition
process continues in
setup view transition
via
perform pending transition operations
If
callbackOptions
is a
StartViewTransitionOptions
, set
viewTransition
’s
active types
to a
clone
of
types
as a
set
Return
viewTransition
2.2.2.
activeViewTransition
Property
Similar to
Document.activeViewTransition
the active view transition of an element is exposed to script via a property on the element.
activeViewTransition
of type
ViewTransition
, readonly, nullable
Returns the
active view transition
for the
element
or null if there is no active view transition.
2.3.
The
ViewTransition
interface
Exposed
Window
interface
ViewTransition
readonly
attribute
Promise
undefined
updateCallbackDone
readonly
attribute
Promise
undefined
ready
readonly
attribute
Promise
undefined
finished
undefined
skipTransition
();
SameObject
readonly
attribute
ViewTransitionTypeSet
types
readonly
attribute
Element
transitionRoot
undefined
waitUntil
Promise
any
promise
);
};
The
ViewTransition
interface represents and controls a single same-document
view transition
i.e. a transition where the starting and ending document are the same,
possibly with changes to the document’s DOM structure.
viewTransition
updateCallbackDone
A promise that fulfills when the promise returned by
updateCallback
fulfills, or rejects when it rejects.
Note:
The View Transition API wraps a DOM change and creates a visual transition.
However, sometimes you don’t care about the success/failure of the transition animation,
you just want to know if and when the DOM change happens.
updateCallbackDone
is for that use-case.)
viewTransition
ready
A promise that fulfills once the pseudo-elements for the transition are created,
and the animation is about to start.
It rejects if the transition cannot begin.
This can be due to misconfiguration, such as duplicate
view-transition-name
s,
or if
updateCallbackDone
returns a rejected promise.
The point that
ready
fulfills
is the ideal opportunity to animate the
view transition pseudo-elements
with the
Web Animation API
viewTransition
finished
A promise that fulfills once the end state is fully visible and interactive to the user.
It only rejects if
updateCallback
returns a rejected promise,
as this indicates the end state wasn’t created.
Otherwise, if a transition fails to begin,
or is skipped (by
skipTransition()
),
the end state is still reached,
so
finished
fulfills.
viewTransition
skipTransition
()
Immediately finish the transition, or prevent it starting.
This never prevents
updateCallback
being called,
as the DOM change is independent of the transition.
See
§ 1.5 Transitions as an enhancement
for more details on this principle.
If this is called before
ready
resolves,
ready
will reject.
If
finished
hasn’t resolved, it will fulfill or reject along with
updateCallbackDone
viewTransition
transitionRoot
The
ViewTransition
’s
root element
For
view transitions
started on the
Document
this is the
document element
viewTransition
waitUntil
()
Delays view transition finish until the given promise is settled
When invoked with Promise
, run
delay finish for promise
steps with
ViewTransition
has the following:
named elements
map
, whose keys are
view transition names
and whose values are
captured elements
Initially a new
map
Note: Since this is associated to the
ViewTransition
, it will be cleaned up when
Clear view transition
is called.
phase
One of the following ordered phases, initially "
pending-capture
":
pending-capture
".
update-callback-called
".
animating
".
done
".
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.
update callback
ViewTransitionUpdateCallback
or null. Initially null.
ready promise
Promise
Initially
a new promise
in
this’s
relevant Realm
update callback done promise
Promise
Initially
a new promise
in
this’s
relevant Realm
Note:
The
ready promise
and
update callback done promise
are immediately created,
so rejections will cause
unhandledrejection
s unless they’re
handled
even if the getters such as
updateCallbackDone
are not accessed.
finished promise
Promise
Initially
a new promise
in
this’s
relevant Realm
marked as handled
Note:
This is
marked as handled
to prevent duplicate
unhandledrejection
s,
as this promise only ever rejects along with the
update callback done promise
transition root pseudo-element
::view-transition
Initially a new
::view-transition
initial snapshot containing block size
tuple
of two numbers (width and height), or null.
Initially null.
Note:
This is used to detect changes in the
snapshot containing block size
which causes the transition to
skip
Discussion of this behavior
active types
ViewTransitionTypeSet
, initially empty.
outbound post-capture steps
Null or a set of steps, initially null.
root element
An
Element
indicating which element is hosting the
ViewTransition
The
finished
getter steps
are to return
this’s
finished promise
The
ready
getter steps
are to return
this’s
ready promise
The
updateCallbackDone
getter steps
are to return
this’s
update callback done promise
The
types
getter steps
are to return
this
’s
active types
The
transitionRoot
getter steps
are to return
this
’s
root element
2.3.1.
The
ViewTransitionTypeSet
Interface
Exposed
Window
interface
ViewTransitionTypeSet
setlike
DOMString
>;
};
The
ViewTransitionTypeSet
object represents a
set
of strings, without special semantics.
Note:
ViewTransitionTypeSet
can contain strings that are invalid for
:active-view-transition-type
, e.g.
strings that are not a

2.3.2.
skipTransition()
Method Steps
The
method steps
for
skipTransition()
are:
If
this
’s
phase
is not "
done
",
then
skip the view transition
for
this
with an "
AbortError
DOMException
3.
CSS properties
3.1.
Tagging Individually Transitioning Subtrees: the
view-transition-name
property
Name:
view-transition-name
Value:
none

Initial:
none
Applies to:
all elements
Inherited:
no
Percentages:
n/a
Computed value:
as specified
Canonical order:
per grammar
Animation type:
discrete
Note:
though
view-transition-name
is
discretely animatable
, animating it doesn’t
affect the running view transition. Rather, it’s a way to set its value in a way that can change
over time or based on a
timeline
. An example for using this would be to change the
view-transition-name
based on
scroll-driven animations
The
view-transition-name
property “tags” an element
for
capture in a view transition
tracking it independently in the
view transition tree
under the specified
view transition name
An element so captured is animated independently of the rest of the page.
none
The
element
will not participate independently in a view transition.

The
element
participates independently in a view transition—​as either an old or new
element
—​with the specified
view transition name
Each
view transition name
is a
tree-scoped name
The values
none
auto
, and
match-element
are excluded from

here.
Note:
If this name is not unique within a single transition
(i.e. if two elements simultaneously specify the same
view transition name
then the
view transition
will abort. It is, however, possible to have non-unique
view transition name
s as long as the elements with these names are never part
of the same transition.
Note:
For the purposes of this API,
if one element has
view transition name
foo
in the old state,
and another element has
view transition name
foo
in the new state,
they are treated as representing different visual states of the same element,
and will be paired in the
view transition tree
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.
If the element’s
principal box
is
fragmented
skipped
or
not rendered
this property has no effect.
See
§ 12 Algorithms
for exact details.
To get the
document-scoped view transition name
for an
Element
element
Let
scopedViewTransitionName
be the
computed value
of
view-transition-name
for
element
If
scopedViewTransitionName
is associated with
element
’s
node document
, then return
scopedViewTransitionName
Otherwise, return
none
3.1.1.
Rendering Consolidation
Elements
captured in a view transition
during a
view transition
or whose
view-transition-name
computed value
is not
none
(at any time):
Form a
stacking context
Are
flattened in 3D transforms
Form a
backdrop root
3.2.
Isolating Scoped View Transition Names: the
view-transition-scope
property
Name:
view-transition-scope
Value:
none
all
Initial:
none
Applies to:
all elements
Inherited:
no
Percentages:
n/a
Computed value:
as specified
Canonical order:
per grammar
Animation type:
discrete
Note:
Although
view-transition-scope
is
discretely animatable
it only has an effect during
view-transition-name
discovery
none
This property has no effect on
view-transition-name
discoverability.
all
Discoverability of
view-transition-name
is limited to the subtree of this element.
This is done by applying
view transition scoping
Such scoping means that any transitions that originate outside of the element
will not discover a non-none
view-transition-name
either on this element
or in its flat-tree descedants.
style
scope
view-transition-scope
all
view-transition-name
view-transition-name
view-transition-name
view-transition-name
style
div
id
div
id
class
scope
div
id
>div
div
div
id
>div
div
script
...
startViewTransition
();
// Will discover "a" and "d" view-transition-names
startViewTransition
();
// Will discover "b" and "c" view-transition-names
...
script
Note:
Starting a transition implies that
this
element has
view-transition-scope: all
for the duration of the transition.
style
view-transition-name
view-transition-name
view-transition-name
view-transition-name
style
div
id
div
id
div
id
>div
div
div
id
>div
div
script
...
startViewTransition
();
// Will discover "b" and "d" view-transition-names
// While b's transition is active and running, the following will only discover
// "a" and "d" view transition names, since b has a forced view-transition-scope: all.
startViewTransition
()
...
script
Note:
Most elements running or planning to run a
scoped view transition
should use
view-transition-scope: all
, to ensure that their
document-scoped view transition names
don’t accidentally interfere with
other
scoped view transitions
in the ancestor chain.
3.3.
Nested View Transition Groups: The
view-transition-group
property
Name:
view-transition-group
Value:
normal
contain
nearest

Initial:
normal
Applies to:
all elements
Inherited:
no
Percentages:
n/a
Computed value:
as specified
Canonical order:
per grammar
Animation type:
discrete
The
view-transition-group
property can be used in conjuction with
view-transition-name
to generate a hierarchy of
named view transition pseudo-element
This property has no effect if
view-transition-name
is
none
normal
The
view-transition-group()
pseudo-element
generated by this element
is a child of the
view-transition-group-children()
pseudo-element
generated by this element’s nearest
view-transition-group()
generating
flat tree
ancestor element
with a non-
normal
view-transition-group
value,
if any.
If no such element is present, the
view-transition-group()
pseudo-element
generated by this element
is a direct child of the
::view-transition
pseudo-element
associated with this view transition.
contain
The
view-transition-group-children()
pseudo-element
generated by this element acts as a container for its descendants.
See
normal
for the effect it has on other elements.
nearest
The
view-transition-group()
pseudo-element
generated by this element
is a child of the
view-transition-group-children()
pseudo-element
generated by this element’s nearest
view-transition-group()
generating
flat tree
ancestor element,
if any.
If no such element is present, the
view-transition-group()
pseudo-element
generated by this element
is a direct child of the
::view-transition
pseudo-element
associated with this view transition.

The
view-transition-group()
pseudo-element
generated by this element
is a child of the
view-transition-group()
pseudo-element
generated by this element’s
flat tree
ancestor element
with a
view-transition-name
value that matches '

', if any.
If no such element is present, the
view-transition-group()
pseudo-element
generated by this element
is a direct child of the
::view-transition
pseudo-element
associated with this view transition.
The
view-transition-group-children()
pseudo-element
is generated
if and only if there is a
view-transition-group()
pseudo-element
attached to it.
The
used value
for
view-transition-group
resolves to a
view-transition-name
in its ancestor chain, or to
none
. When generating the
named view transition pseudo-element
, the
::view-transition-group()
with that name
would create a
::view-transition-group-children()
pseudo-element, which would be the parent of the
::view-transition-group()
generated for this element’s
view-transition-name
3.3.1.
Nested View Transition Group Explanation
This section is non-normative.
By default, setting
view-transition-name
on multiple elements generates a flat
view transition tree
, where all the
::view-transition-group()
pseudo-elements are children of the
::view-transition
pseudo-element.
This is sufficient for many simple use-cases, but there are some styling use-cases that cannot be achieved with a flat tree.
The most prominent use-case is clipping: with a flat tree, all pseudo-elements are clipped to the
snapshot containing block
, so clipping elements in the normal tree would lose their clipping during the view-transition, resulting in a broken visual effect.
The effects that have can have an unexpected visual effect in a flat tree:
Clipping (
overflow
clip-path
border-radius
): clipping affects the children of the element.
opacity
mask-image
and
filter
: These effects that are designed to work on a fully rasterized image of a tree, rather than on each item individually.
3D transforms (
transform-style
transform
perspective
): to display the full range of 3D transform animations, some hierarchy needs to be kept.
To enable these use cases, this specification introduces the concept of nesting view-transition pseudo-elements. By using the
view-transition-group
CSS property,
the author can assign a "parent group" for a generated
::view-transition-group()
pseudo-element, creating a hierarchy in the
view transition tree
3.3.2.
Examples
This example creates a transition where the
view transition tree
is nested instead of flat:
section
class
"container"
article
Content
article
section
.container
view-transition-name
container
.container
::view-transition-group-children
container
clip-path
circle
();
article
view-transition-name
article
view-transition-group
container
The pseudo-element tree for this would be as follows:
::view-transition
├─ ::view-transition-group(container)
│ ├─ ::view-transition-image-pair(container)
│ │ ├─ ::view-transition-old(container)
│ │ └─ ::view-transition-new(container)
│ └─ ::view-transition-group-children(container)
│ ├─ ::view-transition-group(article)
│ │ ├─ ::view-transition-old(article)
│ │ └─ ::view-transition-new(article)
│ └─ ...other nested groups...
└─ …other groups…
By applying the
clip-path
to both the containing element and its generated
::view-transition-group-children()
pseudo-element, we preserve the clip during the transition,
and by applying
view-transition-group
to the internal element referencing the container, we make the tree "nested" in a way that would apply this clipping.
4.
Scoped View Transitions
In addition to
view transitions
triggered on the
document
itself
global view transitions
),
individual
elements
can host their own
scoped view transitions
This enables multiple
view transitions
to run on a page at the same time,
with each animating a different subtree of the document.
It also enables a
view transition
to be affected by the layout and rendering of its subtree,
being affected by scrolling, filters,
z-index
, etc.
("Global"
view transitions
are always rendered on a separate, higher rendering layer
than the rest of the document.)
In order to host a
scoped view transition
an element must have
layout containment
so its painted output can be captured as an atomic unit.
View transitions
whose
root element
is the
document element
are
not
scoped view transitions
They’re
global view transitions
5.
Pseudo-elements
5.1.
Pseudo-element Trees
Note:
This is a general definition for trees of pseudo-elements. If other features need this behavior, these definitions will be moved to
[css-pseudo-4]
pseudo-element root
is a type of
tree-abiding pseudo-element
that is the
root
in a
tree
of
tree-abiding pseudo-elements
known as the
pseudo-element tree
The
pseudo-element tree
defines the document order of its
descendant
tree-abiding pseudo-elements
When a
pseudo-element
participates
in a
pseudo-element tree
its
originating pseudo-element
is its
parent
If a
descendant
pseudo
of a
pseudo-element root
has no other
siblings
then
:only-child
matches that
pseudo
Note:
This means that
::view-transition-new(ident):only-child
will only select
::view-transition-new(ident)
if the parent
::view-transition-image-pair(ident)
contains a single
child
As in, there is no
sibling
::view-transition-old(ident)
5.2.
View Transition Pseudo-elements
The visualization of a
view transition
is represented as a
pseudo-element tree
called the
view transition tree
composed of the
view transition pseudo-elements
defined below.
This tree is built during the
setup transition pseudo-elements
step,
and is rooted under a
::view-transition
pseudo-element
originating
from the
ViewTransition
’s
root element
All of the
view transition pseudo-elements
are selected
from their
ultimate originating element
the
ViewTransition
’s
root element
The
view transition tree
is not exposed to the accessibility tree.
For example,
even though a
::view-transition-group()
pseudo-element
is nested underneath its parent
::view-transition
pseudo-element
for styling and layout purposes,
it’s selected directly on the element hosting the
ViewTransition
if you’d use
.foo::view-transition
you’ll also use
.foo::view-transition-group()
Doing
.foo::view-transition::view-transition-group()
is incorrect,
and won’t select anything.
Once the user-agent has captured both the “old” and “new” states of the document,
it creates a structure of pseudo-elements like the following:
::view-transition
├─ ::view-transition-group(name)
│ └─ ::view-transition-image-pair(name)
│ ├─ ::view-transition-old(name)
│ └─ ::view-transition-new(name)
└─ …other groups…
Each element with a
view-transition-name
is captured separately,
and a
::view-transition-group()
is created for each unique
view-transition-name
For convenience, the
document element
is given the
view-transition-name
"root" in the
user-agent style sheet
Either
::view-transition-old()
or
::view-transition-new()
are absent in cases where the capture does not have an “old” or “new” state.
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.
When using
view-transition-group
property,
an additional
::view-transition-group-children()
pseudo is created
that allows for clipping of descendants and specifying relative transforms.
::view-transition
├─ ::view-transition-group(name)
│ ├─ ::view-transition-image-pair(name)
│ │ ├─ ::view-transition-old(name)
│ │ └─ ::view-transition-new(name)
│ └─ ::view-transition-group-children(name)
│ └─ …groups nested under 'name'…
└─ …other groups…
view-transition-group-children()
element can now be customized to add, for example, clipping with
'overflow: clip'. This would clip any
view-transition-group()
pseudo-elements along with their
descendants.
5.2.1.
Named View Transition Pseudo-elements
Several of the
view transition pseudo-elements
are
named view transition pseudo-elements
which are
functional
tree-abiding
view transition pseudo-elements
associated with a
view transition name
These pseudo-elements take a

as their argument,
and their syntax follows the pattern:
::view-transition-
pseudo

where

selects a
view transition name
and has the following syntax definition:

= '*'

named view transition pseudo-element
selector
only matches
a corresponding
pseudo-element
if its

matches that
pseudo-element
’s
view transition name
i.e. if it is either
or a matching

Note:
The
view transition name
of a
view transition pseudo-element
is set to the
view-transition-name
that triggered its creation.
The specificity of a
named view transition pseudo-element
selector
with a

argument
is equivalent to a
type selector
The specificity of a
named view transition pseudo-element
selector
with a
argument
is zero.
5.2.2.
View Transition Tree Root: the
::view-transition
pseudo-element
The
::view-transition
pseudo-element
is a
tree-abiding pseudo-element
that is also a
pseudo-element root
Its
originating element
is the document’s
document element
and its
containing block
is the
snapshot containing block
Note:
This element serves as the
parent
of all
::view-transition-group()
pseudo-elements.
5.2.3.
View Transition Named Subtree Root: the
::view-transition-group()
pseudo-element
The
::view-transition-group()
pseudo-element
is a
named view transition pseudo-element
that represents a matching named
view transition
capture.
::view-transition-group()
pseudo-element
is generated for each
view transition name
as a
child
of the
::view-transition
pseudo-element
and contains a corresponding
::view-transition-image-pair()
This element initially mirrors the size and position of the “old” element,
or the “new” element if there isn’t an “old” element.
If there’s both an “old” and “new” state,
styles in the
dynamic view transition style sheet
animate this pseudo-element’s
width
and
height
from the size of the old 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.
5.2.4.
View Transition Image Pair Isolation: the
::view-transition-image-pair()
pseudo-element
The
::view-transition-image-pair()
pseudo-element
is a
named view transition pseudo-element
that represents a pair of corresponding old/new
view transition
captures.
This pseudo-element is a
child
of the corresponding
::view-transition-group()
pseudo-element
and contains
a corresponding
::view-transition-old()
pseudo-element
and/or
a corresponding
::view-transition-new()
pseudo-element
(in that order).
This element exists to provide
isolation: isolate
for its children,
and is always present as a
child
of each
::view-transition-group()
This isolation allows the image pair to be blended with non-normal blend modes
without affecting other visual outputs. As such, the developer would typically not
need to add custom styles to the
::view-transition-image-pair()
pseudo-element.
Instead, a typical design would involve styling the
::view-transition-group()
::view-transition-old()
, and
::view-transition-new()
pseudo-elements.
5.2.5.
View Transition Old State Image: the
::view-transition-old()
pseudo-element
The
::view-transition-old()
pseudo-element
is an empty
named view transition pseudo-element
that represents a visual snapshot of the “old” state as a
replaced element
it is omitted if there’s no “old” state to represent.
Each
::view-transition-old()
pseudo-element is a
child
of the corresponding
::view-transition-image-pair()
pseudo-element.
:only-child
can be used to match cases where this element is the only element in the
::view-transition-image-pair()
The appearance of this element can be manipulated with
object-*
properties in the same way that other replaced elements can be.
Note:
The content and
natural dimensions
of the image are captured in
capture the image
and set in
setup transition pseudo-elements
Note:
Additional styles in the
dynamic view transition style sheet
added to animate these pseudo-elements
are detailed in
setup transition pseudo-elements
and
update pseudo-element styles
5.2.6.
View Transition New State Image: the
::view-transition-new()
pseudo-element
The
::view-transition-new()
pseudo-element
(like the analogous
::view-transition-old()
pseudo-element)
is an empty
named view transition pseudo-element
that represents a visual snapshot of the “new” state as a
replaced element
it is omitted if there’s no “new” state to represent.
Each
::view-transition-new()
pseudo-element is a
child
of the corresponding
::view-transition-image-pair()
pseudo-element.
Note:
The content and
natural dimensions
of the image are captured in
capture the image
then set and updated in
setup transition pseudo-elements
and
update pseudo-element styles
5.2.7.
View Transition Group Children: the
::view-transition-group-children()
pseudo-element
The
::view-transition-group-children()
pseudo-element
is created when mandated by the
view-transition-group
property
on either the element itself or on its contained element.
It serves as a container for descendant
view-transition-group()
pseudo-elements.
By default, it is sized to the same size as the corresponding
view-transition-group()
pseudo element.
By default, it has a transparent border that matches the size and shape of the border on the element that caused this structure to be created.
Note:
The size and border setting on this pseudo element allow the developer
to enable clipping of the descedant pseudo elements with a simple
overflow:
clip
property. The developer needs to take care if the original element has
non-overscroll scrollbars, since these scrollbars change the clipping area
from the default provided by this element.
6.
View Transition Layout
The
view transition pseudo-elements
are styled, laid out, and rendered like normal elements.
Global view transitions
originate in the
snapshot containing block
rather than the
initial containing block
and are painted in the
view transition layer
above the rest of the document;
scoped view transitions
are simply rendered after and above all other children of their
root element
6.1.
The Snapshot Containing Block
The
snapshot containing block
is a rectangle
that covers all areas of the window that could potentially display page content
(and is therefore consistent regardless of root scrollbars or
interactive widgets
).
This makes it likely to be consistent for the
document element
’s
old image
and
new element
Within a
child navigable
, the
snapshot containing block
is the union of the navigable’s
viewport
with any
scrollbar gutters
An example of the
snapshot containing block
on a mobile OS.
The snapshot includes the URL bar, as this can be scrolled away.
The keyboard is included as this appears and disappears.
The top and bottom bars are part of the OS rather than the browser, so they’re not included in the snapshot containing block.
An example of the
snapshot containing block
on a desktop OS.
This includes the scrollbars, but does not include the URL bar, as web content never appears in that area.
The
snapshot containing block origin
refers to the top-left corner of the
snapshot containing block
The
snapshot containing block size
refers to the width and height of the
snapshot containing block
as a
tuple
of two numbers.
The
snapshot containing block
is considered to be an
absolute positioning containing block
and a
fixed positioning containing block
for
::view-transition
and its descendants.
6.2.
View Transition Painting Order
This specification introduces a new stacking layer, the
view transition layer
to the end of the painting order established in
CSS2§E Elaborate Description of Stacking Contexts
[CSS2]
Fold this into
[CSS-POSITION-4]
as the interaction with
top layers
needs to be specified.
For a
global view transition
the
::view-transition
pseudo-element generates a new stacking context,
called the
view transition layer
which paints after all other content of the document
(including any content rendered in the
top layer
),
after any filters and effects that are applied to such content.
(It is not subject to such filters or effects,
except insofar as they affect the rendered contents
of the
::view-transition-old()
and
::view-transition-new()
pseudo-elements.)
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 stacking contexts,
since that results in a circular dependency.
Therefore, the
view transition layer
is a sibling of all other content.
When a
Document
’s
active view transition
’s
phase
is "
animating
",
the boxes generated by any element in that
Document
with
captured in a view transition
and its
element contents
except
transition root pseudo-element
’s
inclusive descendants
are not painted (as if they had
opacity: 0
) and
do not respond to hit-testing (as if they had
pointer-events: none
).
Note:
Elements participating in a transition need to skip painting in their DOM location because
their image is painted in the corresponding
::view-transition-new()
pseudo-element instead.
Similarly, hit-testing is skipped because the element’s DOM location does not correspond to where its contents are rendered.
However, there is no change in how these elements are accessed by assistive technologies or the accessibility tree.
6.3.
Scoped View Transition Layout
For a
scoped view transition
, the
::view-transition
pseudo-element
is a child of the
root element
in the
box tree
, but
with some behaviors that are different from ordinary children:
The
::view-transition
pseudo-element generates a stacking context
which paints separately from, and on top of, the painting of the
root element
and its other children.
Note:
A consequence of painting separately is that properties on the root element
that affect the way the root element is painted, such as
opacity
, do not apply
to the
::view-transition
pseudo-element. However, if the root element is captured
in a
::view-transition-group
for its own transition, such properties
will be reflected in the captured image.
If the
root element
has a
scrolling box
, the
::view-transition
pseudo-element is not translated by the scroll position
of the
root element
If the
root element
clips its
overflow
, the
::view-transition
pseudo-element is exempted from that clip.
7.
User Agent Stylesheet
The
global view transition user agent style sheet
is
user-agent origin
style sheet containing the following rules:
:root
view-transition-name
root
::view-transition
position
absolute
inset
::view-transition-group
position
absolute
top
left
animation-duration
0.25
animation-fill-mode
both
::view-transition-image-pair
position
absolute
inset
::view-transition-old
),
::view-transition-new
position
absolute
display
block
inset-block-start
inline-size
100
block-size
auto
::view-transition-image-pair
),
::view-transition-old
),
::view-transition-new
animation-duration
inherit
animation-fill-mode
inherit
animation-delay
inherit
animation-timing-function
inherit
animation-iteration-count
inherit
animation-direction
inherit
animation-play-state
inherit
::view-transition-group-children
position
absolute
inset
border-style
solid
border-color
transparent
/* Default cross-fade transition */
@keyframes
-ua-view-transition-fade-out
to
opacity
@keyframes
-ua-view-transition-fade-in
from
opacity
/* 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
Explanatory Summary
This UA style sheet does several things:
Lay out
:root::view-transition
to cover the entire
snapshot containing block
so that each
:view-transition-group()
child can lay out relative to it.
Note: the placement of the
snapshot containing block
is similar to
position: fixed
For a
scoped view transition
, lay out
::view-transition
to cover the
view transition
root element
Give the
root element
a default
view transition name
to allow it to be independently selected.
Reduce layout interference from the
::view-transition-image-pair()
pseudo-element
so that authors can essentially treat
::view-transition-old()
and
::view-transition-new()
as direct children of
::view-transition-group()
for most purposes.
Inherit animation timing through the tree so that by default,
the animation timing set on a
::view-transition-group()
will dictate the animation timing of all its descendants.
Style the element captures
::view-transition-old()
and
::view-transition-new()
to match the size and position set on
::view-transition-group()
(insofar as possible without breaking their aspect ratios)
as it interpolates between them.
Since the sizing of these elements depends on the mapping between logical and physical coordinates,
dynamic view transition style sheet
copies relevant styles from the DOM elements.
Set up a default quarter-second cross-fade animation
for each
::view-transition-group()
Additional styles are dynamically added to the
user-agent origin
during a
view transition
through the
dynamic view transition style sheet
8.
Cross-document view transitions
8.1.
Overview
This section is non-normative.
8.1.1.
Activation
With same-document view transitions, the author starts a view transition using JavaScript, by calling
startViewTransition
In cross-document view transition, what triggers a view transition is a navigation between two documents, as long as the following conditions are met:
Both documents are of the
same origin
The page is visible throughout the entire course of the navigation;
The user initiates the navigation by interacting with the page, e.g. by clicking a link or submitting a form; or by interacting with the browser UI to do a
traverse
navigation (back/forward). This excludes, for example, navigations initiated by the URL bar;
the navigation didn’t include cross-origin redirects; and
both documents opted in to cross-document view transitions, using the
@view-transition
rule.
See the
lifecycle
section for more details.
8.1.2.
Waiting for the new state to stabilize
In same-document view transitions, the author can indicate when the new state of the transition is in a stable state by using the callback passed to
startViewTransition
Since cross-document view transitions are declarative, there is no such explicit promise. Instead, the user agent relies on the
render-blocking mechanism
to decide when the document has reached a stable state.
In this way, the author can use the
blocking
attribute, to delay the transition until:
All expected scripts are executed, by using the script’s
blocking
attribute on required scripts.
All expected styles are executed, by using the style or link’s
blocking
attribute on required styles.
All expected HTML elements are seen by the parser, using an
expect
HTMLLinkElement
element.
Note:
overusing the render-blocking mechanism could make it so that the old state remains frozen for a long time, resulting in a jarring user experience.
To avoid this, it’s advised to ensure that the render-blocking elements are available in a timely manner.
In this example, the last frame of the old document will be shown, and the animation will be delayed, until all the following conditions are met:
style.css
is applied, to ensure the new state has the correct styles
fixup.js
is run, to ensure the presentation is up to date with script-based fixups.
The
main-article
section is seen and parsed, to ensure enough of the content is loaded before allowing the transition to proceed.

html
head
< !-- This will be render-blocking by default -->
link
rel
"stylesheet"
href
"style.css"
< !-- Since this script fixes up the layout, marking it as render blocking will
ensure it's run before the view transition is activated -->
script
async
href
"fixup.js"
blocking
"render"
>script
< !-- Wait until the main-article element is seen and fully parsed before
activating the transition -->
link
rel
"expect"
href
"#main-article"
blocking
"render"
head
body
header
...
header
main
article
id
"main-article"
...
article
main
article
id
"secondary-article"
...
article
body
html
8.1.3.
Customization
The
ViewTransition
object enables customizing the transition in script.
Same-document view transitions use a single
ViewTransition
object returned from the
startViewTransition
call for the entire lifecycle.
Cross-document view transitions have two
ViewTransition
objects, one in the old document and one in the new document.
8.1.3.1.
Handling the view transition in the old document
The
pageswap
event is fired at the last moment before a document is about to be unloaded and swapped by another document.
It can be used to find out whether a view transition is about to take place, customize it using
types
, make last minute changes to the captured elements, or skip it if necessary.
The
PageSwapEvent
interface has a
viewTransition
object, which would be non-null when the navigation is eligible to a view transition,
and a
activation
object, providing handy information about the navigation, like the URL after redirects.
The transition’s
finished
promise can be used for cleaning up after the transition, in case the document is later restored from BFCache.
8.1.3.2.
Handling the view transition in the new document
The
pagereveal
event is fired right before presenting the first frame of the new document.
It can be used to find out if the view transition is still valid, by querying the
viewTransition
attribute.
Similar to a same-document view transition, the author can now select different
types
, make last minute changes to the captured elements, wait for the transition to be
ready
in order to animate it, or skip it altogether.
8.1.4.
Lifecycle
This section is non-normative.
A successful cross-document view transition goes through the following phases:
In the old
Document
The user initiates a navigation, by clicking a link, submitting a form, pressing the browser’s back button, etc.
Note:
some navigations do not trigger a view-transition, e.g. typing a new address in the URL bar.
When the new
Document
is ready to be activated, the
pageswap
event is fired.
If the navigation is
same origin
, has no cross-origin redirects,
and the old
Document
has
opted in to cross-document view transitions
, the event’s
viewTransition
attribute would be
ViewTransition
object.
The author can now customize the transition, e.g. by mutating its
types
, or
skip
it altogether.
If the
ViewTransition
is not skipped, the state of the old document is
captured
The navigation proceeds: the old
Document
is unloaded, and the new
Document
is now active.
Then, in the new
Document
When the new
Document
is ready for its first
rendering opportunity
, an event named
pagereveal
is fired on the new
Document
, with a
viewTransition
attribute.
This
ViewTransition
’s
updateCallbackDone
promise is already resolved,
and its
captured elements
are populated from the old
Document
This is another opportunity for the author to customize the transition, e.g. by mutating its
types
, or
skip
it altogether.
The state of the new document is
captured
as the "new" state of the transition.
From this point forward, the transition continues in a similar fashion to a same-document transition, as per
activate view transition
8.2.
Examples
To generate the same cross-fade as in the first example
CSS View Transitions 1
§ 1.6 Examples
but across documents, we don’t need JavaScript.
Instead, we opt in to triggering view-transitions on navigation in both page 1 and page 2:
// in both documents:
@view-transition
auto
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.
Note that the
@view-transition
rule can be used together with media queries.
For example, this would only perform the transition when the screen width is greater than:
@view-transition
auto
@media
max-width:
600
px
none
To achieve the effect in
example 5
, we have to do several
things:
Opt-in to navigation-triggered 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 the
pagereveal
event.
In both pages:
@view-transition
auto
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
"pagereveal"
async
event
=>
if
event
viewTransition
return
const
sessionStorage
getItem
"lastClickX"
??
innerWidth
const
sessionStorage
getItem
"lastClickY"
??
innerHeight
const
endRadius
Math
hypot
Math
max
innerWidth
),
Math
max
innerHeight
);
await
event
viewTransition
ready
// Animate the new document's view
document
documentElement
animate
clipPath
`circle(0 at
${
px
${
px)`
`circle(
${
endRadius
px at
${
px
${
px)`
],
},
duration
500
easing
'ease-in'
pseudoElement
'::view-transition-new(root)'
);
})
To choose which elements are captured based on properties of the navigation, and whether certain images are loaded:
In the old page:
window
addEventListener
"pageswap"
event
=>
// For example, the page was hidden, or the navigation is cross-document.
if
event
viewTransition
return
// If you don't want view transition for back/forward navigations...
if
event
activation
navigationType
===
"traverse"
event
viewTransition
skipTransition
();
const
newURL
new
URL
event
activation
entry
url
);
if
newURL
pathname
===
"/details"
&&
thumbnail
complete
thumbnail
classList
add
"transition-to-hero"
);
// This will cleanup the state if the page is restored from BFCache.
event
viewTransition
finished
then
(()
=>
thumbnail
classList
remove
"transition-to-hero"
);
});
});
In the new page:
window
addEventListener
"pagereveal"
event
=>
// For example, the page was hidden, the navigation is cross-document, or the transition was skipped in the old document.
if
event
viewTransition
return
const
oldURL
new
URL
activation
from
url
);
if
newURL
pathname
===
"/list"
event
viewTransition
types
add
"coming-from-list"
);
// This will show the thumbnail until the view transition is finished.
if
hero
complete
setToThumbnail
hero
);
event
viewTransition
finished
then
(()
=>
setToFullResolution
hero
);
})
});
8.3.
Opting in to cross-document view transitions
8.3.1.
The
@view-transition
rule
The
@view-transition
rule is used by a document to indicate that cross-document navigations
should setup and activate a
ViewTransition
The
@view-transition
rule has the following syntax:
@view-transition {

The
@view-transition
rule accepts the
and
types
descriptors.
Note:
as per default behavior, the
@view-transition
rule can be nested inside a
conditional group rule
such as
@media
or
@supports
When the
@view-transition
rule changes for
Document
document
, the user agent must
update the opt-in state for outbound transitions
given
document
Note:
this needs to be cached in the boolean because the result needs to be read
in parallel
, when navigating.
8.3.2.
The
descriptor
Name:
For:
@view-transition
Value:
auto
none
Initial:
none
The '
' descriptor opts in to automatically starting a view transition when performing a navigation of a certain type.
Must be present on both the old and new document.
none
There will be no transition.
auto
The transition will be enabled if the navigation is same-origin, without cross-origin
redirects, and whose
NavigationType
is
traverse
, or
push
or
replace
, with
user navigation involvement
not equal to
"browser UI"
Note:
Navigations excluded from
auto
are for example, navigating
via the URL address bar or clicking a bookmark, as well as any form of user or script initiated
reload
This at-rule conforms with the forward-compatible parsing requirement of CSS;
conformant parsers that don’t understand these rules will ignore them without error.
Any descriptors that are not recognized or implemented by a given user agent,
or whose value does not match the grammars given here or in a future version of this specification,
must be ignored in their entirety;
they do not make the
@view-transition
rule invalid.
8.3.3.
Accessing the
@view-transition
rule using CSSOM
The
CSSViewTransitionRule
represents a
@view-transition
rule.
Exposed
Window
interface
CSSViewTransitionRule
CSSRule
readonly
attribute
CSSOMString
SameObject
readonly
attribute
FrozenArray
CSSOMString
types
};
The
getter step is to return the value of the corresponding
descriptor if one exists, otherwise the empty string.
The
types
getter steps is to return the value of the corresponding
types
descriptor if one exists, otherwise an empty
list
9.
Selective view transitions
9.1.
Overview
This section is non-normative.
For simple pages, with a single view transition, setting the
view-transition-name
property on participating elements should be sufficient.
However, in more complex scenarios, the author might want to declare various view transitions, and only run one of them simultaneously.
For example, sliding the whole page when clicking on the navigation bar, and sorting a list when one of its items is dragged.
To make sure each view transition only captures what it needs to, and different transitions don’t interfere with each other,
this spec introduces the concept of
active types
, alongside the
:active-view-transition
and
:active-view-transition-type()
pseudo-classes.
:active-view-transition
matches the
document element
when it has an
active view transition
, and
:active-view-transition-type()
matches the
document element
if the types in the selectors match the
active view transition
’s
active types
The
ViewTransition
’s
active types
are populated in one of the following ways:
Passed as part of the arguments to
startViewTransition(callbackOptions)
Mutated at any time, using the transition’s
types
Declared for a cross-document view transition, using the
types
descriptor.
9.2.
Examples
For example, the developer might start a transition in the following manner:
document
startViewTransition
({
update
updateTheDOMSomehow
types
"slide-in"
"reverse"
]});
This will activate any of the following selectors:
:root:active-view-transition-type
slide-in
{}
:root:active-view-transition-type
reverse
{}
:root:active-view-transition-type
slide-in
reverse
{}
:root:active-view-transition-type
slide-in
something-else
{}
:root:active-view-transition
{}
While starting a transition without providing transition types, would only activate
:active-view-transition
document
startViewTransition
updateTheDOMSomehow
);
// or
document
startViewTransition
({
update
updateTheDOMSomehow
});
/* This would be active */
:root
:root:active-view-transition
{}
/* This would not be active */
:root:active-view-transition-type
slide-in
{}
:root:active-view-transition-type
any-type-at-all-except-star
{}
9.3.
Selecting based on the active view transition
9.3.1.
The
:active-view-transition
pseudo-class
The
:active-view-transition
pseudo-class applies to the root element of the document, if it has an
active view transition
The
specificity
of an
:active-view-transition
is one pseudo-class selector.
An
:active-view-transition
pseudo-class matches the
document element
when its
node document
has an non-null
active view transition
9.3.2.
The
:active-view-transition-type()
pseudo-class
The
:active-view-transition-type()
pseudo-class applies to the root element of the document, if it has a matching
active view transition
It has the following syntax definition:
:active-view-transition-type(

The
specificity
of an
:active-view-transition-type()
is one pseudo-class selector.
An
:active-view-transition-type()
pseudo-class matches the
document element
when its
node document
has an non-null
active view transition
whose
active types
contains
at least one of the

arguments.
9.4.
Activating the transition type for cross-document view transitions
The
types
descriptor
Name:
types
For:
@view-transition
Value:
none

Initial:
none
The '
types
' descriptor sets the
active types
for the transition
when capturing or performing the transition, equivalent to calling
startViewTransition(callbackOptions)
with that
types
Note:
the
types
descriptor only applies to the
Document
in which it is defined.
The author is responsible for using their chosen set of types in both documents.
10.
Sharing styles between view transition pseudo-elements
10.1.
Overview
This section is non-normative.
When styling multiple elements in the DOM in a similar way, it is common to use the
class
attribute:
setting a name that’s shared across multiple elements, and then using the
class selector
to declare the shared style.
The view transition pseudo-elements
(e.g.
view-transition-group()
) are not defined in the DOM, but rather by using the
view-transition-name
property.
For that purpose, the
view-transition-class
' CSS property provides view transitions with the equivalent of HTML
classes
When an element with a
view-transition-name
also has a
view-transition-class
value, that class would be selectable by the pseudo-elements, as per the
examples
10.2.
Examples
This example creates a transition with each box participating under its own name, while applying
a 1-second duration to the animation of all the boxes:
div
class
"box"
id
"red-box"
>div
div
class
"box"
id
"green-box"
>div
div
class
"box"
id
"yellow-box"
>div
div.box
view-transition-class
any-box
width
100
px
height
100
px
#red-box
view-transition-name
red-box
background
red
#green-box
view-transition-name
green-box
background
green
#yellow-box
view-transition-name
yellow-box
background
yellow
/* The following style would apply to all the boxes, thanks to 'view-transition-class' */
::view-transition-group
*.any-box
animation-duration
10.3.
The
view-transition-class
property
Name:
view-transition-class
Value:
none

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-class
can be used to apply the same style rule to multiple
named view transition pseudo-elements
which may have a different
view-transition-name
While
view-transition-name
is used to match between the element in the old state with its corresponding element in the new state,
view-transition-class
is used
only to apply styles using the view transition pseudo-elements
::view-transition-group()
::view-transition-image-pair()
::view-transition-old()
::view-transition-new()
).
Note that
view-transition-class
by itself doesn’t mark an element for capturing, it is only used as an additional
way to style an element that already has a
view-transition-name
none
No class would apply to the
named view transition pseudo-elements
generated for this element.

All of the specified

values (apart from
none
) are applied when used in
named view transition pseudo-element
selectors.
none
is an invalid

for
view-transition-class
, even when combined with another

Each 'view transition class' is a
tree-scoped name
Note:
If the same
view-transition-name
is specified for an element both in the old and new states of the transition,
only the
view-transition-class
values from the new state apply. This also applies for cross-document view transitions:
classes from the old document would only apply if their corresponding
view-transition-name
was not specified in the new document.
10.4.
Additions to named view transition pseudo-elements
The
named view transition pseudo-elements
view-transition-group()
view-transition-image-pair()
view-transition-old()
view-transition-new()
are extended to support the following syntax:
::view-transition-group(

::view-transition-image-pair(

::view-transition-old(

::view-transition-new(

where

works as previously defined, and

has the following syntax definition:





= ['.'

When interpreting the above grammar, white space is forbidden:
Between

and

Between any of the components of

named view transition pseudo-element
selector
which has one or more

values
in its

would only match an element if the
class list
value in
named elements
for the pseudo-element’s
view-transition-name
contains
all of those values.
The
specificity
of a
named view transition pseudo-element
selector
with either:

with a

; or

with at least one

is equivalent to a
type selector
The
specificity
of a
named view transition pseudo-element
selector
with a
argument and with an empty

is zero.
11.
Determining
view-transition-name
automatically
11.1.
Overview
This section is non-normative.
For an element to participate in a view transition, it needs to receive a unique
view-transition-name
This can be tedious and verbose when multiple elements are involved in the same view transition, especially in cases where many of those are same-element transitions,
as in, the element has the same
view-transition-name
in the old and new state.
To make this easier, setting the
view-transition-name
to
auto
would generate a
view-transition-name
for the element, or take it from the element’s
id
if present.
11.2.
Examples
In this example, view transition is used to sort a list in an animated way:
ul
li
Item 1
li
li
Item 2
li
li
Item 3
li
li
Item 4
li
...
ul
Ordinarily, each of these items would have to receive a unique
view-transition-name
li
nth-child
view-transition-name
item1
li:nth-child
view-transition-name
item2
li:nth-child
view-transition-name
item3
li:nth-child
view-transition-name
item4
...
With
auto
or
match-element
, this CSS would work:
li
view-transition-name
auto
/* or */
view-transition-name: match-element
The
auto
and
match-element
keywords have a minor
difference, where
auto
would use the element’s
id
as the
view-transition-name
if it exists, making it potentially work across documents, while
match-element
only matches
based on element identity.
11.3.
Additions to
view-transition-name
In addition to the existing values, the
view-transition-name
also accepts an
auto
keyword.
To resolve the
used value
of
view-transition-name
for
element
Let
computed
be the
computed value
of
view-transition-name
If
computed
is
none
, return null.
If
computed
is a

, return
computed
Assert:
computed
is
auto
or
match-element
If
computed
is
auto
element
has an associated
id
, and
computed
is associated with the same
root
as
element
’s
root
, then return a unique string starting with "
-ua-
".
Two elements with the same
id
must return the same string, regardless of their
node document
Note:
this means that a
::part()
pseudo-element wouldn’t resolve to its matching element’s
id
Return a unique string starting with "
-ua-
". The string should remain consistent and unique for this element and
Document
, at least for the lifetime of
element
’s
node document
’s
active view transition
Note:
When used in a cross-document view transition, generated
auto
values never match, resulting in separate
::view-transition-group()
pseudo-elements, one exiting and one entering.
view-transition-name
generated by
auto
is a
tree-scoped name
12.
Algorithms
12.1.
Data Structures
12.1.1.
Additions to
Document
Document
additionally has:
active view transition
ViewTransition
or null. Initially null.
rendering suppression for view transitions
a boolean. Initially false.
While a
Document
’s
rendering suppression for view transitions
is true,
all pointer hit testing must target its
document element
ignoring all other
elements
Note:
This does not affect pointers that are
captured
dynamic view transition style sheet
style sheet
Initially a new
style sheet
in the
user-agent origin
, ordered after the
global view transition user agent style sheet
Note:
This is used to hold dynamic styles relating to transitions.
show view transition tree
A boolean. Initially false.
When this is true,
this
’s
active view transition
’s
transition root pseudo-element
renders as a child of
this
’s
document element
with
this
’s
document element
is its
originating element
Note:
The position of the
transition root pseudo-element
within the
document element
does not matter, as the
transition root pseudo-element
’s
containing block
is the
snapshot containing block
update callback queue
list
, initially empty.
inbound view transition params
view transition params
, or null.
Initially null.
can initiate outbound view transition
a boolean.
Initially false.
Note:
this value can be read
in parallel
while navigating.
wait until promise count
an integer, initially 0.
Represents the count of promises that have been added via
waitUntil
function
and have not settled.
12.1.2.
Additions to Elements
Elements
have a
captured in a view transition
boolean, initially false.
Note:
This spec uses CSS’s definition of
element
, which includes
pseudo-elements
12.1.3.
Captured elements
captured element
is a
struct
with the following:
old image
an 2D bitmap or null. Initially null.
old width
old height
an
unrestricted double
, initially zero.
old transform

, initially the
identity transform function
old writing-mode
Null or a
writing-mode
, initially null.
old direction
Null or a
direction
, initially null.
old text-orientation
Null or a
text-orientation
, initially null.
old mix-blend-mode
Null or a
mix-blend-mode
, initially null.
old backdrop-filter
Null or a
backdrop-filter
, initially null.
old color-scheme
Null or a
color-scheme
, initially null.
new element
an
element
or null. Initially null.
class list
list
of strings, initially empty.
containing group name
Null or a string, initially null.
transform from snapshot containing block
matrix
or null, initially null.
old border width
border-width
used value
(top, right, bottom and left pixel values) or null, initially null.
In addition, a
captured element
has the following
style definitions
group keyframes
CSSKeyframesRule
or null. Initially null.
group animation name rule
CSSStyleRule
or null. Initially null.
group styles rule
CSSStyleRule
or null. Initially null.
image pair isolation rule
CSSStyleRule
or null. Initially null.
image animation name rule
CSSStyleRule
or null. Initially null.
Note:
These are used to update, and later remove styles
from a
document
’s
dynamic view transition style sheet
12.1.4.
Serializable
view transition params
view transition params
is a
struct
whose purpose is to serialize view transition information across documents.
It has the following
items
named elements
map
, whose keys are strings and whose values are
captured elements
initial snapshot containing block size
tuple
of two numbers (width and height).
12.2.
Perform pending transition operations
This algorithm is invoked as a part of
update the rendering loop
in the html spec.
To
perform pending transition operations
given a
Document
document
, perform the following steps:
If
document
’s
active view transition
is not null, then:
If
document
’s
active view transition
’s
phase
is "
pending-capture
",
then
setup view transition
for
document
’s
active view transition
Otherwise, if
document
’s
active view transition
’s
phase
is "
animating
",
then
handle transition frame
for
document
’s
active view transition
12.3.
Resolving the
@view-transition
rule
To
resolve @view-transition rule
for a
Document
document
Note:
this is called in both the old and new document.
If
document
’s
visibility state
is "
hidden
",
then return "
skip transition
".
Let
matchingRule
be the last
@view-transition
rule in
document
If
matchingRule
is not found, then return "
skip transition
".
If
matchingRule
’s
descriptor’s
computed value
is
none
, then return "
skip transition
".
Assert:
matchingRule
’s
descriptor’s
computed value
is
auto
Let
typesDescriptor
be
matchingRule
’s
types
descriptor.
If
typesDescriptor
’s
computed value
is
none
, then return a
set
« ».
Return a
set
of strings corresponding to
typesDescriptor
’s
computed value
12.4.
Setup single-document view transition
To
setup view transition
for a
ViewTransition
transition
perform the following steps:
Note:
This algorithm captures the current state of the document,
calls the transition’s
ViewTransitionUpdateCallback
then captures the new state of the document.
Let
document
be
transition
’s
relevant global object’s
associated document
Flush the update callback queue
Note:
this ensures that any changes to the DOM scheduled by other skipped transitions are done before the old state for this transition is captured.
Capture the old state
for
transition
If failure is returned, then
skip the view transition
for
transition
with an "
InvalidStateError
DOMException
in
transition
’s
relevant Realm
and return.
Set
document
’s
rendering suppression for view transitions
to true.
Queue a global task
on the
DOM manipulation task source
given
transition
’s
relevant global object
to perform 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.
If
transition
’s
phase
is "
done
", then abort these steps.
Note:
This happens if
transition
was
skipped
before this point.
schedule the update callback
for
transition
Flush the update callback queue
To
activate view transition
for a
ViewTransition
transition
perform the following steps:
If
transition
’s
phase
is "
done
", then return.
Note:
This happens if
transition
was
skipped
before this point.
Set
transition
’s
relevant global object’s
associated document
’s
rendering suppression for view transitions
to false.
If
transition
’s
initial snapshot containing block size
is not equal to the
snapshot containing block size
then
skip
transition
with an "
InvalidStateError
DOMException
in
transition
’s
relevant Realm
and return.
Capture the new state
for
transition
If failure is returned, then
skip
transition
with an "
InvalidStateError
DOMException
in
transition
’s
relevant Realm
and return.
For each
capturedElement
of
transition
’s
named elements
values
If
capturedElement
’s
new element
is not null,
then set
capturedElement
’s
new element
’s
captured in a view transition
to true.
Setup transition pseudo-elements
for
transition
Update pseudo-element styles
for
transition
If failure is returned, then
skip the view transition
for
transition
with an "
InvalidStateError
DOMException
in
transition
’s
relevant Realm
and return.
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
12.4.1.
Capture the old state
To
capture the old state
for
ViewTransition
transition
Let
document
be
transition
’s
relevant global object’s
associated document
Let
namedElements
be
transition
’s
named elements
Let
usedTransitionNames
be a new
set
of strings.
Let
captureElements
be a new
list
of elements.
If the
snapshot containing block size
exceeds an
implementation-defined
maximum, then return failure.
Set
transition
’s
initial snapshot containing block size
to the
snapshot containing block size
For each
element
of every
element
that is
connected
and has a
node document
equal to
document
in
paint order
Note:
We iterate in paint order to ensure that this order is cached in
namedElements
This defines the DOM order for ::view-transition-group pseudo-elements, such that the element at the bottom of the paint stack generates the first pseudo child of ::view-transition.
If any
flat tree
ancestor of this
element
skips its contents
, then
continue
If any
flat tree
inclusive ancestor
of this
element
up to but not including
transition
’s
root element
has
contain: view-transition
continue
If
element
has more than one
box fragment
, then
continue
Note:
We might want to enable transitions for fragmented elements in future versions.
See
#8900
Note:
box fragment
here does not refer to fragmentation of
inline boxes
across
line boxes
Such inlines can participate in a transition.
Let
transitionName
be the
element
’s
document-scoped view transition name
If
transitionName
is
none
or
element
is
not rendered
then
continue
If
usedTransitionNames
contains
transitionName
, then:
For each
element
in
captureElements
Set
element
’s
captured in a view transition
to false.
Return failure.
If
any other
active view transition
contains
element
in its
captured elements
then for each such
active view transition
in
tree order
of their corresponding
root elements
skip
that view transition with an "
AbortError
DOMException
in
document
’s
relevant Realm
Append
transitionName
to
usedTransitionNames
Set
element
’s
captured in a view transition
to true.
Append
element
to
captureElements
The algorithm continues in a separate loop to ensure that
captured in a view transition
is set on all elements participating in this capture before it is read by future steps in the algorithm.
For each
element
in
captureElements
Let
capture
be a new
captured element
struct.
Set
capture
’s
old image
to the result of
capturing the image
of
element
Let
originalRect
be
snapshot containing block
if
element
is the
document element
otherwise, the
element
’s
border box
Set
capture
’s
old width
to
originalRect
’s
width
Set
capture
’s
old height
to
originalRect
’s
height
Set
capture
’s
old transform
to a

that would map
element
’s
border box
from the
snapshot containing block origin
to its
current visual position.
Set
capture
’s
old writing-mode
to the
computed value
of
writing-mode
on
element
Set
capture
’s
old direction
to the
computed value
of
direction
on
element
Set
capture
’s
old text-orientation
to the
computed value
of
text-orientation
on
element
Set
capture
’s
old mix-blend-mode
to the
computed value
of
mix-blend-mode
on
element
Set
capture
’s
old backdrop-filter
to the
computed value
of
backdrop-filter
on
element
Set
capture
’s
old color-scheme
to the
computed value
of
color-scheme
on
element
Let
transitionName
be the
computed value
of
view-transition-name
for
element
Set
namedElements
transitionName
] to
capture
For each
element
in
captureElements
Set
element
’s
captured in a view transition
to false.
12.4.2.
Capture the new state
To
capture the new state
for
ViewTransition
transition
Let
document
be
transition
’s
relevant global object’s
associated document
Let
namedElements
be
transition
’s
named elements
Let
usedTransitionNames
be a new
set
of strings.
For each
element
of every
element
that is
connected
and has a
node document
equal to
document
in
paint order
If any
flat tree
ancestor of this
element
skips its contents
, then
continue
Let
transitionName
be
element
’s
document-scoped view transition name
If
transitionName
is
none
or
element
is
not rendered
then
continue
If
element
has more than one
box fragment
, then
continue
If
usedTransitionNames
contains
transitionName
then return failure.
Append
transitionName
to
usedTransitionNames
If
namedElements
transitionName
] does not
exist
then set
namedElements
transitionName
] to a new
captured element
struct.
Note:
We intentionally add this struct to the end of this ordered map.
This implies than names which only exist in the new DOM (entry animations) will be painted on top of names only in the old DOM (exit animations) and names in both DOMs (paired animations).
This might not be the right layering for all cases. See
issue 8941
Set
namedElements
transitionName
]'s
new element
to
element
12.4.3.
Setup transition pseudo-elements
To
setup transition pseudo-elements
for a
ViewTransition
transition
Note:
This algorithm constructs the pseudo-element tree for the transition,
and generates initial styles.
The structure of the pseudo-tree is covered at a higher level in
§ 5.2 View Transition Pseudo-elements
Let
document
be
transition
’s
relevant global object’s
associated document
Set
document
’s
show view transition tree
to true.
For each
transitionName
capturedElement
of
transition
’s
named elements
Let
group
be a new
::view-transition-group()
with its
view transition name
set to
transitionName
Append
group
to
transition
’s
transition root pseudo-element
Let
imagePair
be a new
::view-transition-image-pair()
with its
view transition name
set to
transitionName
Append
imagePair
to
group
If
capturedElement
’s
old image
is not null, then:
Let
old
be a new
::view-transition-old()
with its
view transition name
set to
transitionName
displaying
capturedElement
’s
old image
as its
replaced
content.
Append
old
to
imagePair
If
capturedElement
’s
new element
is not null, then:
Let
new
be a new
::view-transition-new()
with its
view transition name
set to
transitionName
Note:
The styling of this pseudo is handled in
update pseudo-element styles
Append
new
to
imagePair
If
capturedElement
’s
old image
is null, then:
Assert
capturedElement
’s
new element
is not null.
Set
capturedElement
’s
image animation name rule
to a new
CSSStyleRule
representing the following CSS,
and append it to
document
’s
dynamic view transition style sheet
:root::view-transition-new
transitionName
animation-name
-ua-view-transition-fade-in
Note:
The above code example contains variables to be replaced.
If
capturedElement
’s
new element
is null, then:
Assert
capturedElement
’s
old image
is not null.
Set
capturedElement
’s
image animation name rule
to a new
CSSStyleRule
representing the following CSS,
and append it to
document
’s
dynamic view transition style sheet
:root::view-transition-old
transitionName
animation-name
-ua-view-transition-fade-out
Note:
The above code example contains variables to be replaced.
If both of
capturedElement
’s
old image
and
new element
are not null, then:
Let
transform
be
capturedElement
’s
old transform
Let
width
be
capturedElement
’s
old width
Let
height
be
capturedElement
’s
old height
Let
backdropFilter
be
capturedElement
’s
old backdrop-filter
Set
capturedElement
’s
group keyframes
to a new
CSSKeyframesRule
representing the following CSS,
and append it to
document
’s
dynamic view transition style sheet
@keyframes
-ua-view-transition-group-anim-
transitionName
from
transform
transform
width
width
height
height
backdrop-filter
backdropFilter
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
dynamic view transition style sheet
:root::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
dynamic view transition style sheet
:root::view-transition-image-pair
transitionName
isolation
isolate
Note:
The above code example contains variables to be replaced.
Set
capturedElement
’s
image animation name rule
to a new
CSSStyleRule
representing the following CSS,
and append it to
document
’s
dynamic view transition style sheet
:root::view-transition-old
transitionName
animation-name
-ua-view-transition-fade-out
-ua-mix-blend-mode-plus-lighter
:root::view-transition-new
transitionName
animation-name
-ua-view-transition-fade-in
-ua-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.
12.5.
Setup cross-document view transition
12.5.1.
Setting up the view transition in the old
Document
12.5.1.1.
Check eligibility for outbound cross-document view transition
To check if a
navigation can trigger a cross-document view-transition?
given
Document
oldDocument
, a
Document
newDocument
, a
NavigationType
navigationType
, and a boolean
isBrowserUINavigation
Note:
this is called during navigation, potentially
in parallel
If the user agent decides to display an
implementation-defined
navigation experience, e.g. a gesture-based transition for a back navigation,
the user agent may ignore the author-defined view transition. If that is the case, return false.
If
oldDocument
’s
can initiate outbound view transition
is false, then return false.
If
navigationType
is
reload
, then return false.
If
oldDocument
’s
origin
is not
same origin
as
newDocument
’s
origin
, then return false.
If
newDocument
was created via cross-origin redirects
and
newDocument
’s
latest entry
is null, then return false.
Note:
Document
’s
latest entry
would be null if this is a new navigation, rather than a restore from BFCache.
If
navigationType
is
traverse
, then return true.
If
isBrowserUINavigation
is true, then return false.
Return true.
12.5.1.2.
Setup the outbound transition when ready to swap pages
To
setup cross-document view-transition
given a
Document
oldDocument
Document
newDocument
, and
proceedWithNavigation
, which is an algorithm accepting nothing:
Note:
This is called from the HTML spec.
Assert
: These steps are running as part of a
task
queued on
oldDocument
If
oldDocument
’s
can initiate outbound view transition
is false, then return null.
Let
transitionTypesFromRule
be the result of
resolving the @view-transition rule
for
oldDocument
Assert
transitionTypesFromRule
is not "
skip transition
".
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 we fire the
pagereveal
event.
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
Set
outboundTransition
’s
active types
to
transitionTypesFromRule
Note:
the
active types
are not shared between documents.
Manipulating the
types
in the new document does not affect the types in
newDocument
which would be read from the
types
descriptor once
newDocument
is revealed.
Note:
the
ViewTransition
is skipped once the old document is hidden.
Set
outboundTransition
’s
outbound post-capture steps
to the following steps given a
view transition params
-or-null
params
Set
newDocument
’s
inbound view transition params
to
params
Note:
The inbound transition is activated after the dispatch of
pagereveal
to ensure mutations made in this event apply to the captured new state.
To skip the transition after a timeout, the user agent may perform the following steps
in parallel
Wait for an
implementation-defined
duration
Queue a global task
on the
DOM manipulation task source
given
newDocument
’s
relevant global object
to perform the following step:
If
newDocument
’s
inbound view transition params
is
params
, then set
newDocument
’s
inbound view transition params
to null.
Call
proceedWithNavigation
Set
oldDocument
’s
active view transition
to
outboundTransition
Note:
The process continues in
perform pending transition operations
The user agent should display the currently displayed frame until either:
The
pagereveal
event is fired.
its
active view transition
’s
phase
is "
done
".
Note:
this is to ensure that there are no unintended flashes between displaying the old and new state, to keep the transition smooth.
Return
outboundTransition
12.5.1.3.
Update the opt-in flag to reflect the current state
To
update the opt-in state for outbound transitions
for a
Document
document
If
document
has been revealed
, and the result of
resolving the @view-transition rule
is not "
skip transition
",
then set
document
’s
can initiate outbound view transition
to true.
Otherwise, set
document
’s
can initiate outbound view transition
to false.
12.5.1.4.
Proceed with navigation if view transition is skipped
Append the following steps to
skip the view transition
given a
ViewTransition
transition
If
transition
’s
outbound post-capture steps
is not null, then run
transition
’s
outbound post-capture steps
with null.
Note:
This is written in a monkey-patch manner, and will be merged into the algorithm once the L1 spec graduates.
12.5.1.5.
Proceed with cross-document view transition after capturing the old state
Prepend the following step to the
Perform pending transition operations
algorithm given a
Document
document
If
document
’s
active view transition
is not null and its
outbound post-capture steps
is not null, then:
Assert:
document
’s
active view transition
’s
phase
is "
pending-capture
".
Let
viewTransitionParams
be null;
Set
document
’s
rendering suppression for view transitions
to true.
Though
capture the old state
appears here as a synchronous step, it is in fact an asynchronous step
as rendering an element into an image cannot be done synchronously. This should be more explicit in the L1 spec.
Capture the old state
for
transition
If this succeeded, then set
viewTransitionParams
to a new
view transition params
whose
named elements
is a
clone
of
transition
’s
named elements
and whose
initial snapshot containing block size
is
transition
’s
initial snapshot containing block size
Set
document
’s
rendering suppression for view transitions
to false.
Call
transition
’s
outbound post-capture steps
given
viewTransitionParams
Note:
This is written in a monkey-patch manner, and will be merged into the algorithm once the L1 spec graduates.
12.5.2.
Activating the view transition in the new
Document
To
resolve inbound cross-document view-transition
for
Document
document
Assert
document
is
fully active
Assert
document
has been revealed
is true.
Update the opt-in state for outbound transitions
for
document
Let
inboundViewTransitionParams
be
document
’s
inbound view transition params
If
inboundViewTransitionParams
is null, then return null.
Set
document
’s
inbound view transition params
to null.
If
document
’s
active view transition
is not null, then return null.
Note:
this means that starting a same-document transition before revealing the document would cancel a pending cross-document transition.
Resolve @view-transition rule
for
document
and let
resolvedRule
be the result.
If
resolvedRule
is "
skip transition
", then return null.
Let
transition
be a new
ViewTransition
in
document
’s
relevant Realm
whose
named elements
is
inboundViewTransitionParams
’s
named elements
and
initial snapshot containing block size
is
inboundViewTransitionParams
’s
initial snapshot containing block size
Set
document
’s
active view transition
to
transition
Resolve
transition
’s
update callback done promise
with undefined.
Set
transition
’s
phase
to "
update-callback-called
".
Set
transition
’s
active types
to
resolvedRule
Return
transition
12.5.3.
Capturing the
view-transition-class
When capturing the old or new state for an element, perform the following steps given a
captured element
capture
and an
element
element
Set
capture
’s
class list
to the
computed value
of
element
’s
view-transition-class
, if it is associated with
element
’s
node document
Note:
This is written in a monkey-patch manner, and will be merged into the algorithm once the L1 spec graduates.
12.5.4.
Capturing and applying
view-transition-group
12.5.4.1.
Resolving the
view-transition-group
value
To get the
document-scoped view transition group
of an
Element
element
, perform the following steps:
Let
computedGroup
be the
computed value
of element’s
view-transition-group
property.
If
computedGroup
is associated with
element
’s
node document
, return
computedGroup
Return
normal
12.5.4.2.
Resolving the containing group name
To resolve the
nearest containing group name
of an
Element
element
, perform the following steps given a
ViewTransition
viewTransition
Assert:
element
participates in
viewTransition
Let
ancestorGroup
be
element
’s nearest
flat tree
ancestor
who participates in
viewTransition
and whose
document-scoped view transition group
is not
normal
If
ancestorGroup
exists, return
ancestorGroup
’s
document-scoped view transition name
Return
none
12.5.4.3.
Resolving the group name
To resolve the
used group name
of an
Element
element
, perform the following steps given a
ViewTransition
transition
Assert:
element
participates in
transition
Let
group
be
element
’s
document-scoped view transition group
Let
containingGroupName
be
element
’s
nearest containing group name
given
transition
Return the first matching statement, switching on
group
normal
contain
containingGroupName
Note: an element with
contain
becomes the
nearest containing group name
for its descendants.
nearest
: The
document-scoped view transition name
of the element’s nearest
flat tree
ancestor which participates in the
transition

group
if the element has a
flat tree
ancestor
whose
document-scoped view transition name
is
group
and participates in
transition
; Otherwise
containingGroupName
12.5.4.4.
Compute the old
view-transition-group
When
capturing the old state for an element
, perform the following steps given a
captured element
capturedElement
, a
ViewTransition
transition
, and an
element
element
Set
capturedElement
’s
containing group name
to
element
’s
used group name
given
transition
Set
capturedElement
’s
old border width
to
element
’s
used
border-width
12.5.4.5.
Compute the new
view-transition-group
When
capturing the new state for an element
, perform the following steps given a
captured element
capturedElement
ViewTransition
transition
, and an
element
element
Set
capturedElement
’s
containing group name
to
element
’s
used group name
given
transition
12.5.4.6.
Reparent a
::view-transition-group()
to its specified containing group
When
setting up the transition pseudo-element
for a
captured element
capturedElement
, given a
transitionName
and a
transition
Let
containingGroupName
be
capturedElement
’s
containing group name
If
containingGroupName
is null, return.
Let
groupContainerElement
be
transition
’s
named elements
containingGroupName
].
Let
group
be the
::view-transition-group()
whose
view transition name
is set to
transitionName
Let
childrenContainerGroup
be the
::view-transition-group-children()
whose
view transition name
is set to
containingGroupName
If
childrenContainerGroup
does not exist:
Generate it and append to the
::view-transition-group()
whose
view transition name
is set to
containingGroupName
Append
group
to
childrenContainerGroup
When setting the animation keyframes given
transform
adjust
transform
given
groupContainerElement
Note:
It is TBD how this is resolved when the old and new groups mismatch. See
Issue 10631
12.5.4.7.
Adjust the group’s
transform
to be relative to its containing
::view-transition-group()
When
updating the style of the transition pseudo-element
, perform the following steps before setting the
group styles rule
, given a
captured element
capturedElement
, given a
transform
and a
ViewTransition
transition
Let
childrenTransform
be
transform
Set
capturedElement
’s
transform from snapshot containing block
to
transform
If
capturedElement
’s
containing group name
is not null, then:
Let
groupContainerElement
be
transition
’s
named elements
capturedElement
’s
containing group name
Adjust
transform
given
groupContainerElement
To
adjust nested view transition group transform
given a
transform
and a
captured element
groupContainerElement
Let
childrenTransform
be
groupContainerElement
’s
transform from snapshot containing block
If
childrenTransform
is null, set it to
groupContainerElement
’s
old transform
Translate
childrenTransform
by
groupContainerElement
’s
old border width
’s left and top components.
Multiply
transform
by the inverse matrix of
childrenTransform
12.6.
Call the update callback
To
call the update callback
of a
ViewTransition
transition
Note:
This is guaranteed to happen for every
ViewTransition
even if the transition is
skipped
The reasons for this are discussed in
§ 1.5 Transitions as an enhancement
Assert
transition
’s
phase
is "
done
", or before "
update-callback-called
".
If
transition
’s
phase
is not "
done
", then set
transition
’s
phase
to "
update-callback-called
".
Let
callbackPromise
be null.
If
transition
’s
update callback
is null,
then set
callbackPromise
to
a promise resolved with
undefined,
in
transition
’s
relevant Realm
Otherwise, set
callbackPromise
to the result of
invoking
transition
’s
update callback
Let
fulfillSteps
be to following steps:
Resolve
transition
’s
update callback done promise
with undefined.
Activate
transition
Let
rejectSteps
be the following steps given
reason
Reject
transition
’s
update callback done promise
with
reason
If
transition
’s
phase
is "
done
", then return.
Note:
This happens if
transition
was
skipped
before this point.
Mark as handled
transition
’s
ready promise
Note:
transition
’s
update callback done promise
will provide the
unhandledrejection
This step avoids a duplicate.
Skip the view transition
transition
with
reason
React
to
callbackPromise
with
fulfillSteps
and
rejectSteps
To skip a transition after a timeout, the user agent may perform the following steps
in parallel
Wait for an implementation-defined
duration
Queue a global task
on the
DOM manipulation task source
given
transition
’s
relevant global object
, to perform the following steps:
If
transition
’s
phase
is "
done
", then return.
Note:
This happens if
transition
was
skipped
before this point.
Skip
transition
with a "
TimeoutError
DOMException
To
schedule the update callback
given a
ViewTransition
transition
Append
transition
to
transition
’s
relevant settings object
’s
update callback queue
Queue a global task
on the
DOM manipulation task source
given
transition
’s
relevant global object
, to
flush the update callback queue
To
flush the update callback queue
given a
Document
document
For each
transition
in
document
’s
update callback queue
call the update callback
given
transition
Set
document
’s
update callback queue
to an empty list.
12.7.
Skip the view transition
To
skip the view transition
for
ViewTransition
transition
with reason
reason
Let
document
be
transition
’s
relevant global object’s
associated document
Assert
transition
’s
phase
is not "
done
".
If
transition
’s
phase
is before "
update-callback-called
",
then
schedule the update callback
for
transition
Set
rendering suppression for view transitions
to false.
If
document
’s
active view transition
is
transition
Clear view transition
transition
Set
transition
’s
phase
to "
done
".
Reject
transition
’s
ready promise
with
reason
Note:
The
ready promise
may already be resolved at this point,
if
skipTransition()
is called after we start animating.
In that case, this step is a no-op.
Resolve
transition
’s
finished promise
with the result of
reacting
to
transition
’s
update callback done promise
If the promise was fulfilled, then return undefined.
Note:
Since the rejection of
transition
’s
update callback done promise
isn’t explicitly handled here,
if
transition
’s
update callback done promise
rejects,
then
transition
’s
finished promise
will reject with the same reason.
12.8.
View transition page-visibility change steps
The
view transition page-visibility change steps
given
Document
document
are:
Queue a global task
on the
DOM manipulation task source
given
document
’s
relevant global object
to perform the following steps:
If
document
’s
visibility state
is "
hidden
", then:
If
document
’s
active view transition
is not null, then
skip
document
’s
active view transition
with an "
InvalidStateError
DOMException
Otherwise,
assert
active view transition
is null.
Set
document
’s
inbound view transition params
to null.
Note:
this is called from the HTML spec.
12.9.
Capture the image
To
capture the image
given an
element
element
, perform the following steps.
They return an image.
If
element
is the
document element
, then:
Render the region of document
(including its
canvas background
and any
top layer
content)
that intersects the
snapshot containing block
on a transparent canvas the size of the
snapshot containing block
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.
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 this canvas as an image.
The natural size of the image is equal to the
snapshot containing block
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
Return the portion of this canvas that includes
element
’s
ink overflow rectangle
as an image.
The
natural dimensions
of this image must be those of its
principal
border box
and its origin must correspond to that
border box
’s origin,
such that the image represents the contents of this
border box
and any captured
ink overflow
is represented outside these bounds.
Note:
When this image is rendered as a
replaced element
at its
natural size
it will display with the size and contents of element’s
principal box
with any captured
ink overflow
overflowing its
content box
12.9.1.
Capture rendering characteristics
The
capture rendering characteristics
are as follows:
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 applied on the element and its descendants, such as
opacity
and
filter
, are applied to the capture.
Effects applied to the element from its ancestors are ignored.
Implementations may clip the rendered contents if the
ink overflow rectangle
exceeds some
implementation-defined
maximum.
However, the captured image should include, at the very least, the contents of
element
that intersect with the
snapshot containing block
Implementations may adjust the rasterization quality to account for elements with a large
ink overflow area
that are transformed into view.
Implementations may also adjust the rasterization quality for elements whose
ink overflow rectangle
does not intersect with the
snapshot containing block
To avoid a broken experience if the element ends up becoming visible, the captured image should include, at the very least, some low-quality representation of the contents rather than transparent pixels.
Note:
This allows efficiency in resource usage and rasterization performance for elements that are away from the viewport and might not become visible at all,
while maintaining a visual effect close enough to the author’s intent.
For each
descendant
of
shadow-including descendant
Element
and
pseudo-element
of
element
if
descendant
is
captured in a view transition
then skip painting
descendant
Note:
This is necessary since the descendant will generate its own snapshot which will be displayed and animated independently.
To
delay finish for promise
, given promise
If
is settled, abort the remainder of the steps and return.
Increment
this
’s
wait until promise count
Upon fulfillment
or
rejection
of
Decrement
this
’s
wait until promise count
Note:
If
this
’s
wait until promise count
is 0, the transition will finish at the next
rendering opportunity
12.10.
Handle transition frame
To
handle transition frame
given a
ViewTransition
transition
Let
document
be
transition
’s
relevant global object’s
associated document
Let
hasActiveAnimations
be a boolean, initially false.
For each
element
of
transition
’s
transition root pseudo-element
’s
inclusive descendants
For each
animation
whose
timeline
is a
document timeline
associated with
document
and contains at least one
associated effect
whose
effect target
is
element
set
hasActiveAnimations
to true if any of the following conditions are true:
animation
’s
play state
is
paused
or
running
document
’s
pending animation event queue
has any events associated with
animation
If
hasActiveAnimations
is false and
this
’s
wait until promise count
is 0:
Set
transition
’s
phase
to "
done
".
Clear view transition
transition
Resolve
transition
’s
finished promise
Return.
If
transition
’s
initial snapshot containing block size
is not equal to the
snapshot containing block size
then
skip the view transition
for
transition
with an "
InvalidStateError
DOMException
in
transition
’s
relevant Realm
and return.
Update pseudo-element styles
for
transition
If failure is returned, then
skip the view transition
for
transition
with an "
InvalidStateError
DOMException
in
transition
’s
relevant Realm
and return.
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.
12.11.
Update pseudo-element styles
To
update pseudo-element styles
for a
ViewTransition
transition
For each
transitionName
capturedElement
of
transition
’s
named elements
Let
width
height
transform
writingMode
direction
textOrientation
mixBlendMode
backdropFilter
and
colorScheme
be null.
If
capturedElement
’s
new element
is null, then:
Set
width
to
capturedElement
’s
old width
Set
height
to
capturedElement
’s
old height
Set
transform
to
capturedElement
’s
old transform
Set
writingMode
to
capturedElement
’s
old writing-mode
Set
direction
to
capturedElement
’s
old direction
Set
textOrientation
to
capturedElement
’s
old text-orientation
Set
mixBlendMode
to
capturedElement
’s
old mix-blend-mode
Set
backdropFilter
to
capturedElement
’s
old backdrop-filter
Set
colorScheme
to
capturedElement
’s
old color-scheme
Otherwise:
Return failure if any of the following conditions are true:
capturedElement
’s
new element
has a
flat tree
ancestor that
skips its contents
capturedElement
’s
new element
is
not rendered
capturedElement
has more than one
box fragment
Note:
Other rendering constraints are enforced via
capturedElement
’s
new element
being
captured in a view transition
Let
newRect
be the
snapshot containing block
if
capturedElement
’s
new element
is the
document element
otherwise,
capturedElement
’s
border box
Set
width
to the current width of
newRect
Set
height
to the current height of
newRect
Set
transform
to a transform that would map
newRect
from the
snapshot containing block origin
to its current visual position.
Set
writingMode
to the
computed value
of
writing-mode
on
capturedElement
’s
new element
Set
direction
to the
computed value
of
direction
on
capturedElement
’s
new element
Set
textOrientation
to the
computed value
of
text-orientation
on
capturedElement
’s
new element
Set
mixBlendMode
to the
computed value
of
mix-blend-mode
on
capturedElement
’s
new element
Set
backdropFilter
to the
computed value
of
backdrop-filter
on
capturedElement
’s
new element
Set
colorScheme
to the
computed value
of
color-scheme
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
transition
’s
relevant global object’s
associated document
’s
dynamic view transition style sheet
Otherwise, update
capturedElement
’s
group styles rule
to match the following CSS:
:root::view-transition-group
transitionName
width
width
height
height
transform
transform
writing-mode
writingMode
direction
direction
text-orientation
textOrientation
mix-blend-mode
mixBlendMode
backdrop-filter
backdropFilter
color-scheme
colorScheme
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()
with the
view transition name
transitionName
Set
new
’s
replaced element
content to the result of
capturing the image
of
capturedElement
’s
new element
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")
12.12.
Clear view transition
To
clear view transition
of a
ViewTransition
transition
Let
document
be
transition
’s
relevant global object’s
associated document
Assert
document
’s
active view transition
is
transition
For each
capturedElement
of
transition
’s
named elements
values
If
capturedElement
’s
new element
is not null,
then set
capturedElement
’s
new element
’s
captured in a view transition
to false.
For each
style
of
capturedElement
’s
style definitions
If
style
is not null,
and
style
is in
document
’s
dynamic view transition style sheet
then remove
style
from
document
’s
dynamic view transition style sheet
Set
document
’s
show view transition tree
to false.
Set
document
’s
active view transition
to null.
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.
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:
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
§  Security Considerations
as the same restriction applies for captured cross-origin iframes.
A same-origin navigation might still occur via a cross-origin redirect, e.g.
links to
which redirects back to
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 the
Document
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.
See
Issue #8684
and
WICG/view-transitions#200
for
detailed discussion.
Appendix A. Changes
This appendix is
informative
Changes from
2024-05-16 Working Draft
Add description of nested view transition groups, which was partially missing.
Update wording to use
opacity: 0
instead of
visibility: hidden
. See
issue 12629
Replace
contain: view-transition
with
view-transition-scope
property (
pending #13123
Reorder sections, editorial changes, added several issues, updated scoped view transition wording.
Add waitUntil() (
#9901
First pass at layered capture (
#10585
Allow transitions when traversing into a document that was created using cross-origin redirects (
#11063
#11063)
Clarify a few nesting details (
#10780
and
#10633
Allow
auto
as a keyword for
view-transition-name
#8320
Clarify timeout behavior for inbound view transition (
#10800
When hiding the document, and inbound cross-document view transition should be skipped. (
#9822
Rename UpdateCallback to something more specific.
Clarify that CSSViewTransitionRule returns an empty string for invalid/missing navigation descriptor (
#10654
Initial spec for nested view transitions (
#10334
view-transition-class
is a tree-scoped name (
#10529
Stop extending CSSRule with obsolete pattern (See
#10606
Added
activeViewTransition
attribute (
#12407
Conformance
Document conventions
Conformance requirements are expressed with a combination of
descriptive assertions and RFC 2119 terminology. The key words “MUST”,
“MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”,
“RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this
document are to be interpreted as described in RFC 2119.
However, for readability, these words do not appear in all uppercase
letters in this specification.
All of the text of this specification is normative except sections
explicitly marked as non-normative, examples, and notes.
[RFC2119]
Examples in this specification are introduced with the words “for example”
or are set apart from the normative text with
class="example"
like this:
This is an example of an informative example.
Informative notes begin with the word “Note” and are set apart from the
normative text with
class="note"
, like this:
Note, this is an informative note.
Advisements are normative sections styled to evoke special attention and are
set apart from other normative text with

, like
this:
UAs MUST provide an accessible alternative.
Tests
Tests relating to the content of this specification
may be documented in “Tests” blocks like this one.
Any such block is non-normative.
Conformance classes
Conformance to this specification
is defined for three conformance classes:
style sheet
CSS
style sheet
renderer
UA
that interprets the semantics of a style sheet and renders
documents that use them.
authoring tool
UA
that writes a style sheet.
A style sheet is conformant to this specification
if all of its statements that use syntax defined in this module are valid
according to the generic CSS grammar and the individual grammars of each
feature defined in this module.
A renderer is conformant to this specification
if, in addition to interpreting the style sheet as defined by the
appropriate specifications, it supports all the features defined
by this specification by parsing them correctly
and rendering the document accordingly. However, the inability of a
UA to correctly render a document due to limitations of the device
does not make the UA non-conformant. (For example, a UA is not
required to render color on a monochrome monitor.)
An authoring tool is conformant to this specification
if it writes style sheets that are syntactically correct according to the
generic CSS grammar and the individual grammars of each feature in
this module, and meet all other conformance requirements of style sheets
as described in this module.
Partial implementations
So that authors can exploit the forward-compatible parsing rules to
assign fallback values, CSS renderers
must
treat as invalid (and
ignore
as appropriate
) any at-rules, properties, property values, keywords,
and other syntactic constructs for which they have no usable level of
support. In particular, user agents
must not
selectively
ignore unsupported component values and honor supported values in a single
multi-value property declaration: if any value is considered invalid
(as unsupported values must be), CSS requires that the entire declaration
be ignored.
Implementations of Unstable and Proprietary Features
To avoid clashes with future stable CSS features,
the CSSWG recommends
following best practices
for the implementation of
unstable
features and
proprietary extensions
to CSS.
Non-experimental implementations
Once a specification reaches the Candidate Recommendation stage,
non-experimental implementations are possible, and implementors should
release an unprefixed implementation of any CR-level feature they
can demonstrate to be correctly implemented according to spec.
To establish and maintain the interoperability of CSS across
implementations, the CSS Working Group requests that non-experimental
CSS renderers submit an implementation report (and, if necessary, the
testcases used for that implementation report) to the W3C before
releasing an unprefixed implementation of any CSS features. Testcases
submitted to W3C are subject to review and correction by the CSS
Working Group.
Further information on submitting testcases and implementation reports
can be found from on the CSS Working Group’s website at
Questions should be directed to the
public-css-testsuite@w3.org
mailing list.
Index
Terms defined by this specification
activate view transition
, in § 12.4
active types
, in § 2.3
:active-view-transition
, in § 9.3.1
active view transition
, in § 12.1.1
activeViewTransition
attribute for Document
, in § 2.1.2
attribute for Element
, in § 2.2.2
:active-view-transition-type()
, in § 9.3.2
adjust nested view transition group transform
, in § 12.5.4.7
all
, in § 3.2
auto
dfn for view-transition-name
, in § 11.3
value for @view-transition/navigation
, in § 8.3.2
call the update callback
, in § 12.6
can initiate outbound view transition
, in § 12.1.1
captured element
, in § 12.1.3
captured in a view transition
, in § 12.1.2
capture rendering characteristics
, in § 12.9.1
capture the image
, in § 12.9
capture the new state
, in § 12.4.2
capture the old state
, in § 12.4.1
capturing the image
, in § 12.9
class list
, in § 12.1.3
clear view transition
, in § 12.12
contain
, in § 3.3
containing group name
, in § 12.1.3
CSSViewTransitionRule
, in § 8.3.3

value for view-transition-group
, in § 3.3
value for view-transition-name
, in § 3.1
+
, in § 10.3
delay finish for promise
, in § 12.9.1
document-scoped view transition group
, in § 12.5.4.1
document-scoped view transition name
, in § 3.1
dynamic view transition style sheet
, in § 12.1.1
finished
, in § 2.3
finished promise
, in § 2.3
flush the update callback queue
, in § 12.6
global view transitions
, in § 4
global view transition user agent style sheet
, in § 7
group animation name rule
, in § 12.1.3
group keyframes
, in § 12.1.3
group styles rule
, in § 12.1.3
handle transition frame
, in § 12.10
image animation name rule
, in § 12.1.3
image pair isolation rule
, in § 12.1.3
inbound view transition params
, in § 12.1.1
initial snapshot containing block size
dfn for ViewTransition
, in § 2.3
dfn for view transition params
, in § 12.1.4
named elements
dfn for ViewTransition
, in § 2.3
dfn for view transition params
, in § 12.1.4
named view transition pseudo-elements
, in § 5.2.1
attribute for CSSViewTransitionRule
, in § 8.3.3
descriptor for @view-transition
, in § 8.3.2
dfn for @view-transition
, in § 8.3.2
navigation can trigger a cross-document view-transition?
, in § 12.5.1.1
nearest
, in § 3.3
nearest containing group name
, in § 12.5.4.2
new element
, in § 12.1.3
none
dfn for view-transition-scope
, in § 3.2
value for @view-transition/navigation
, in § 8.3.2
value for view-transition-class
, in § 10.3
value for view-transition-name
, in § 3.1
normal
, in § 3.3
old backdrop-filter
, in § 12.1.3
old border width
, in § 12.1.3
old color-scheme
, in § 12.1.3
old direction
, in § 12.1.3
old height
, in § 12.1.3
old image
, in § 12.1.3
old mix-blend-mode
, in § 12.1.3
old text-orientation
, in § 12.1.3
old transform
, in § 12.1.3
old width
, in § 12.1.3
old writing-mode
, in § 12.1.3
outbound post-capture steps
, in § 2.3
perform pending transition operations
, in § 12.2
phase
, in § 2.3
pseudo-element root
, in § 5.1
pseudo-element tree
, in § 5.1

, in § 10.4

, in § 10.4

, in § 5.2.1
ready
, in § 2.3
ready promise
, in § 2.3
rendering suppression for view transitions
, in § 12.1.1
resolve inbound cross-document view-transition
, in § 12.5.2
resolve @view-transition rule
, in § 12.3
root element
, in § 2.3
schedule the update callback
, in § 12.6
scoped view transitions
, in § 4
setup cross-document view-transition
, in § 12.5.1.2
setup transition pseudo-elements
, in § 12.4.3
setup view transition
, in § 12.4
show view transition tree
, in § 12.1.1
skip the view transition
, in § 12.7
skipTransition()
, in § 2.3.2
snapshot containing block
, in § 6.1
snapshot containing block origin
, in § 6.1
snapshot containing block size
, in § 6.1
startViewTransition()
method for Document
, in § 2.1.1
method for Element
, in § 2.2.1
startViewTransition(callbackOptions)
method for Document
, in § 2.1.1
method for Element
, in § 2.2.1
StartViewTransitionOptions
, in § 2.1
style definitions
, in § 12.1.3
transform from snapshot containing block
, in § 12.1.3
transitionRoot
, in § 2.3
transition root pseudo-element
, in § 2.3
types
attribute for CSSViewTransitionRule
, in § 8.3.3
attribute for ViewTransition
, in § 2.3
descriptor for @view-transition
, in § 9.4
dfn for @view-transition
, in § 9.4
dict-member for StartViewTransitionOptions
, in § 2.1
update
, in § 2.1
update callback
, in § 2.3
updateCallbackDone
, in § 2.3
update callback done promise
, in § 2.3
update callback queue
, in § 12.1.1
update pseudo-element styles
, in § 12.11
update the opt-in state for outbound transitions
, in § 12.5.1.3
used group name
, in § 12.5.4.3
::view-transition
, in § 5.2.2
@view-transition
, in § 8.3.1
ViewTransition
, in § 2.3
view-transition-class
, in § 10.3
::view-transition-group()
, in § 5.2.3
view-transition-group
, in § 3.3
::view-transition-group-children()
, in § 5.2.7
::view-transition-image-pair()
, in § 5.2.4
view transition layer
, in § 6.2
view transition name
, in § 3.1
view-transition-name
, in § 3.1
::view-transition-new()
, in § 5.2.6
::view-transition-old()
, in § 5.2.5
view transition page-visibility change steps
, in § 12.8
view transition params
, in § 12.1.4
view transition pseudo-elements
, in § 5.2
view transitions
, in § 1
view-transition-scope
, in § 3.2
view transition scoping
, in § 3.2
view transition tree
, in § 5.2
ViewTransitionTypeSet
, in § 2.3.1
ViewTransitionUpdateCallback
, in § 2.1
waitUntil(promise)
, in § 2.3
wait until promise count
, in § 12.1.1
Terms defined by reference
[COMPOSITING-2]
defines the following terms:
isolation
mix-blend-mode
[CSS-2025]
defines the following terms:
style sheet
[CSS-ANIMATIONS-1]
defines the following terms:
CSSKeyframesRule
[CSS-BACKGROUNDS-3]
defines the following terms:
canvas background
[CSS-BORDERS-4]
defines the following terms:
border-radius
border-width
[CSS-BOX-4]
defines the following terms:
border box
content box
[CSS-BREAK-4]
defines the following terms:
box fragment
fragment
[CSS-CASCADE-5]
defines the following terms:
computed value
used value
user-agent origin
[CSS-COLOR-4]
defines the following terms:
opacity
[CSS-COLOR-ADJUST-1]
defines the following terms:
color-scheme
[CSS-CONDITIONAL-3]
defines the following terms:
@media
@supports
conditional group rule
[CSS-CONTAIN-2]
defines the following terms:
contain
element contents
layout containment
skips its contents
[CSS-DISPLAY-3]
defines the following terms:
atomic inline
inline-level
internal ruby box
[CSS-DISPLAY-4]
defines the following terms:
box tree
containing block
initial containing block
principal box
replaced element
root element
[CSS-IMAGES-3]
defines the following terms:
natural dimension
natural size
[CSS-IMAGES-4]
defines the following terms:
element-not-rendered
[CSS-MASKING-1]
defines the following terms:
clip-path
mask-image
[CSS-OVERFLOW-3]
defines the following terms:
ink overflow
ink overflow area
ink overflow rectangle
overflow
scrollbar gutter
[CSS-POSITION-3]
defines the following terms:
absolute positioning containing block
fixed positioning containing block
[CSS-POSITION-4]
defines the following terms:
top layer
[CSS-PSEUDO-4]
defines the following terms:
tree-abiding pseudo-elements
[CSS-SHADOW-1]
defines the following terms:
::part()
flat tree
tree-scoped name
[CSS-SIZING-3]
defines the following terms:
height
width
[CSS-SYNTAX-3]
defines the following terms:

[CSS-TRANSFORMS-1]
defines the following terms:
identity transform function
transform
[CSS-TRANSFORMS-2]
defines the following terms:

perspective
transform-style
[CSS-UI-4]
defines the following terms:
pointer-events
[CSS-VALUES-4]
defines the following terms:

[CSS-VIEWPORT-1]
defines the following terms:
interactive-widget
[CSS-WRITING-MODES-3]
defines the following terms:
direction
[CSS-WRITING-MODES-4]
defines the following terms:
text-orientation
writing-mode
[CSS2]
defines the following terms:
element
stacking context
viewport
z-index
[CSSOM-1]
defines the following terms:
CSSOMString
CSSRule
CSSStyleRule
[CSSOM-VIEW-1]
defines the following terms:
layout viewport
scrolling box
[DOM]
defines the following terms:
Document
Element
ancestor
child
class
connected
descendant
document
document element
ID
inclusive ancestor
inclusive descendant
node document
origin
parent
participate
root
shadow-including descendant
sibling
tree
tree order
[FILTER-EFFECTS-1]
defines the following terms:
filter
[FILTER-EFFECTS-2]
defines the following terms:
Backdrop Root
backdrop-filter
[GEOMETRY-1]
defines the following terms:
height
matrix
width
[HR-TIME-3]
defines the following terms:
duration
[HTML]
defines the following terms:
HTMLLinkElement
NavigateEvent
NavigationType
PageSwapEvent
activation
associated Document
blocking
(for HTMLScriptElement)
blocking
(for HTMLStyleElement)
child navigable
cross-origin isolated capability
DOM manipulation task source
expect
fully active
has been revealed
in parallel
latest entry
pagereveal
pageswap
push
queue a global task
reactivate
relevant global object
relevant realm
relevant settings object
reload
render-blocking mechanism
rendering opportunity
replace
same origin
sessionStorage
signal
task
traverse
unhandledrejection
viewTransition
(for PageRevealEvent)
viewTransition
(for PageSwapEvent)
visibility state
was created via cross-origin redirects
[INFRA]
defines the following terms:
append
(for list)
append
(for set)
assert
clone
(for list)
clone
(for map)
contain
continue
exist
for each
(for list)
for each
(for map)
implementation-defined
item
list
map
set
struct
tuple
values
[INTERSECTION-OBSERVER]
defines the following terms:
IntersectionObserver
[POINTEREVENTS4]
defines the following terms:
pointer capture
[SCROLL-ANIMATIONS-1]
defines the following terms:
scroll-driven animations
[SELECTORS-3]
defines the following terms:
[SELECTORS-4]
defines the following terms:
:only-child
class selector
functional pseudo-element
originating element
originating pseudo-element
pseudo-elements
selector
specificity
type selector
ultimate originating element
[WEB-ANIMATIONS-1]
defines the following terms:
associated effect
discrete
document timeline
effect target
paused
pending animation event queue
play state
running
timeline
[WEBIDL]
defines the following terms:
AbortError
DOMException
DOMString
Exposed
FrozenArray
InvalidStateError
Promise
SameObject
TimeoutError
a new promise
a promise resolved with
any
getter steps
invoke
mark as handled
method steps
react
reacting
reject
resolve
sequence
setlike
this
undefined
unrestricted double
upon fulfillment
upon rejection
References
Normative References
[COMPOSITING-2]
Compositing and Blending Module Level 2
. Editor's Draft. URL:
[CSS-2025]
Chris Lilley; et al.
CSS Snapshot 2025
. URL:
[CSS-ANIMATIONS-1]
David Baron; et al.
CSS Animations Level 1
. URL:
[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper.
CSS Backgrounds and Borders Module Level 3
. URL:
[CSS-BORDERS-4]
Elika Etemad; et al.
CSS Borders and Box Decorations Module Level 4
. URL:
[CSS-BOX-4]
Elika Etemad.
CSS Box Model Module Level 4
. URL:
[CSS-BREAK-4]
Rossen Atanassov; Elika Etemad.
CSS Fragmentation Module Level 4
. URL:
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr..
CSS Cascading and Inheritance Level 5
. URL:
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou.
CSS Color Module Level 4
. URL:
[CSS-COLOR-ADJUST-1]
Elika Etemad; et al.
CSS Color Adjustment Module Level 1
. URL:
[CSS-CONTAIN-2]
Tab Atkins Jr.; Florian Rivoal; Vladimir Levin.
CSS Containment Module Level 2
. URL:
[CSS-DISPLAY-3]
Elika Etemad; Tab Atkins Jr..
CSS Display Module Level 3
. URL:
[CSS-DISPLAY-4]
Elika Etemad; Tab Atkins Jr..
CSS Display Module Level 4
. URL:
[CSS-IMAGES-3]
Tab Atkins Jr.; Elika Etemad; Lea Verou.
CSS Images Module Level 3
. URL:
[CSS-IMAGES-4]
Elika Etemad; Tab Atkins Jr.; Lea Verou.
CSS Images Module Level 4
. URL:
[CSS-MASKING-1]
Dirk Schulze; Brian Birtles; Tab Atkins Jr..
CSS Masking Module Level 1
. URL:
[CSS-OVERFLOW-3]
Elika Etemad; Florian Rivoal.
CSS Overflow Module Level 3
. URL:
[CSS-POSITION-3]
Elika Etemad; Tab Atkins Jr..
CSS Positioned Layout Module Level 3
. URL:
[CSS-POSITION-4]
Elika Etemad; Tab Atkins Jr..
CSS Positioned Layout Module Level 4
. URL:
[CSS-PSEUDO-4]
Elika Etemad; Alan Stearns.
CSS Pseudo-Elements Module Level 4
. URL:
[CSS-SHADOW-1]
CSS Shadow Module Level 1
. Editor's Draft. URL:
[CSS-SYNTAX-3]
Tab Atkins Jr.; Simon Sapin.
CSS Syntax Module Level 3
. URL:
[CSS-TRANSFORMS-1]
Simon Fraser; et al.
CSS Transforms Module Level 1
. URL:
[CSS-TRANSFORMS-2]
Tab Atkins Jr.; et al.
CSS Transforms Module Level 2
. URL:
[CSS-UI-4]
Tab Atkins Jr.; Florian Rivoal.
CSS Basic User Interface Module Level 4
. URL:
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad.
CSS Values and Units Module Level 4
. URL:
[CSS-VIEW-TRANSITIONS-1]
Tab Atkins Jr.; Jake Archibald; Khushal Sagar.
CSS View Transitions Module Level 1
. URL:
[CSS-VIEWPORT-1]
Florian Rivoal; Emilio Cobos Álvarez.
CSS Viewport Module Level 1
. URL:
[CSS-WRITING-MODES-3]
Elika Etemad; Koji Ishii.
CSS Writing Modes Level 3
. URL:
[CSS-WRITING-MODES-4]
Elika Etemad; Koji Ishii.
CSS Writing Modes Level 4
. URL:
[CSS2]
Bert Bos; et al.
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification
. URL:
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez.
CSS Object Model (CSSOM)
. URL:
[CSSOM-VIEW-1]
Simon Fraser; Emilio Cobos Álvarez.
CSSOM View Module
. URL:
[DOM]
Anne van Kesteren.
DOM Standard
. Living Standard. URL:
[FILTER-EFFECTS-1]
Dirk Schulze; Dean Jackson.
Filter Effects Module Level 1
. URL:
[FILTER-EFFECTS-2]
Filter Effects Module Level 2
. Editor's Draft. URL:
[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv.
Geometry Interfaces Module Level 1
. URL:
[HR-TIME-3]
Yoav Weiss.
High Resolution Time
. URL:
[HTML]
Anne van Kesteren; et al.
HTML Standard
. Living Standard. URL:
[INFRA]
Anne van Kesteren; Domenic Denicola.
Infra Standard
. Living Standard. URL:
[INTERSECTION-OBSERVER]
Stefan Zager; Emilio Cobos Álvarez; Traian Captan.
Intersection Observer
. URL:
[RFC2119]
S. Bradner.
Key words for use in RFCs to Indicate Requirement Levels
. March 1997. Best Current Practice. URL:
[SELECTORS-3]
Tantek Çelik; et al.
Selectors Level 3
. URL:
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr..
Selectors Level 4
. URL:
[WEB-ANIMATIONS-1]
Brian Birtles; et al.
Web Animations
. URL:
[WEBIDL]
Edgar Chen; Timothy Gu.
Web IDL Standard
. Living Standard. URL:
Non-Normative References
[CSS-CONDITIONAL-3]
Chris Lilley; David Baron; Elika Etemad.
CSS Conditional Rules Module Level 3
. URL:
[CSS-SIZING-3]
Tab Atkins Jr.; Elika Etemad.
CSS Box Sizing Module Level 3
. URL:
[POINTEREVENTS4]
Patrick Lauke; Robert Flack.
Pointer Events
. URL:
[SCROLL-ANIMATIONS-1]
Brian Birtles; et al.
Scroll-driven Animations
. URL:
Property Index
Name
Value
Initial
Applies to
Inh.
%ages
Anim­ation type
Canonical order
Com­puted value
view-transition-class
none | +
none
all elements
no
n/a
discrete
per grammar
as specified
view-transition-group
normal | contain | nearest |
normal
all elements
no
n/a
discrete
per grammar
as specified
view-transition-name
none |
none
all elements
no
n/a
discrete
per grammar
as specified
view-transition-scope
none | all
none
all elements
no
n/a
discrete
per grammar
as specified
@view-transition
Descriptors
Name
Value
Initial
auto | none
none
types
none | +
none
IDL Index
partial
interface
Document
ViewTransition
startViewTransition
optional
ViewTransitionUpdateCallback
or
StartViewTransitionOptions
callbackOptions
= {}
);
readonly
attribute
ViewTransition
activeViewTransition
};
callback
ViewTransitionUpdateCallback
Promise
any
> ();
dictionary
StartViewTransitionOptions
ViewTransitionUpdateCallback
update
null
sequence
DOMString
>?
types
null
};
partial
interface
Element
ViewTransition
startViewTransition
optional
ViewTransitionUpdateCallback
or
StartViewTransitionOptions
callbackOptions
= {}
);
readonly
attribute
ViewTransition
activeViewTransition
};

Exposed
Window
interface
ViewTransition
readonly
attribute
Promise
undefined
updateCallbackDone
readonly
attribute
Promise
undefined
ready
readonly
attribute
Promise
undefined
finished
undefined
skipTransition
();
SameObject
readonly
attribute
ViewTransitionTypeSet
types
readonly
attribute
Element
transitionRoot
undefined
waitUntil
Promise
any
promise
);
};

Exposed
Window
interface
ViewTransitionTypeSet
setlike
DOMString
>;
};

Exposed
Window
interface
CSSViewTransitionRule
CSSRule
readonly
attribute
CSSOMString
SameObject
readonly
attribute
FrozenArray
CSSOMString
types
};
Issues Index
Fold this into
[CSS-POSITION-4]
as the interaction with
top layers
needs to be specified.
Though
capture the old state
appears here as a synchronous step, it is in fact an asynchronous step
as rendering an element into an image cannot be done synchronously. This should be more explicit in the L1 spec.
MDN
Document/startViewTransition
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
ViewTransition/finished
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
ViewTransition/ready
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
ViewTransition/skipTransition
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
ViewTransition/updateCallbackDone
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
ViewTransition
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
view-transition-name
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
::view-transition-group
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
::view-transition-image-pair
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
::view-transition-new
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
::view-transition-old
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile
MDN
::view-transition
In only one current engine.
Firefox
None
Safari
None
Chrome
111+
Opera
Edge
111+
Edge (Legacy)
IE
None
Firefox for Android
iOS Safari
Chrome for Android
Android WebView
Samsung Internet
Opera Mobile