Skip to content

Commit 606ed9a

Browse files
committed
[css-view-transitions-2] Begin integrating scoped view transitions.
1 parent e3e787f commit 606ed9a

File tree

1 file changed

+185
-42
lines changed

1 file changed

+185
-42
lines changed

css-view-transitions-2/Overview.bs

Lines changed: 185 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,12 @@ spec:css2; type:dfn; text:viewport
123123
Level 2 defines the following,
124124
extending the model in [[CSS-VIEW-TRANSITIONS-1]]:
125125

126-
* <a href="#cross-document-view-transitions">Cross-document view transitions</a>, including the ''@view-transition'' rule and the algorithms
126+
* [[#cross-document-view-transitions|Cross-document view transitions]], including the ''@view-transition'' rule and the algorithms
127127
that enable the cross-document view transition lifecycle.
128-
* <a href="#selective-vt">Selective view transitions</a>, a way to match styles based on the existence of an [=active view transition=],
128+
* [[#selective-vt|Selective view transitions]], a way to match styles based on the existence of an [=active view transition=],
129129
and more specifically based on the active view transition being of a certain type.
130-
* <a href="#shared-style-with-vt-classes">Sharing styles between view transition pseudo-elements</a>, a way to declare a style once,
131-
and use it for multiple view transition pseudo-elements. This includes the 'view-transition-class' property, and <a href="#pseudo-element-class-additions">additions to named pseudo-elements</a>
130+
* [[#shared-style-with-vt-classes|Sharing styles between view transition pseudo-elements]], a way to declare a style once,
131+
and use it for multiple view transition pseudo-elements. This includes the 'view-transition-class' property, and [[#pseudo-element-class-additions|additions to named pseudo-elements]]
132132

133133
## Separating Visual Transitions from DOM Updates ## {#separating-transitions}
134134

@@ -365,6 +365,10 @@ spec:css2; type:dfn; text:viewport
365365

366366
<div class=example>
367367
Building on the previous example,
368+
the simple "whole document" transition displayed a visible judder in the purple heading bar,
369+
and had the heading text always slide to the left
370+
even when it was "moving" to the right in the 1->2 transition.
371+
To fix these issues,
368372
the header and text within the header can be given their own ''::view-transition-group()''s for the transition:
369373

370374
```css
@@ -540,8 +544,6 @@ spec:css2; type:dfn; text:viewport
540544

541545
Each [=view transition name=] is a [=tree-scoped name=].
542546

543-
Note: Since currently only document-scoped view transitions are supported, only view transition names that are associated with the document are respected.
544-
545547
The values <css>none</css>, <css>auto</css>, and <css>match-element</css> are excluded from <<custom-ident>> here.
546548

547549
Note: If this name is not unique
@@ -552,7 +554,7 @@ spec:css2; type:dfn; text:viewport
552554
Note: For the purposes of this API,
553555
if one element has [=view transition name=] ''foo'' in the old state,
554556
and another element has [=view transition name=] ''foo'' in the new state,
555-
they are treated as representing different visual state of the same element,
557+
they are treated as representing different visual states of the same element,
556558
and will be paired in the [=view transition tree=].
557559
This may be confusing, since the elements themselves are not necessarily referring to the same object,
558560
but it is a useful model to consider them to be visual states of the same conceptual page entity.
@@ -581,6 +583,27 @@ spec:css2; type:dfn; text:viewport
581583
- Are [[css-transforms-2#grouping-property-values|flattened in 3D transforms]].
582584
- Form a [=backdrop root=].
583585

586+
## Isolating Scoped View Transition Names: the ''contain/view-transition'' containment value ## {#contain-view-transition}
587+
588+
<pre class="propdef partial">
589+
Name: contain
590+
New Values: view-transition
591+
</pre>
592+
593+
The ''contain: view-transition'' value establishes <dfn export>view transition name containment</dfn> on an element.
594+
This causes any [=document-scoped view transition names=] to only be visible
595+
for [=view transitions=] scoped to this element or its descendants.
596+
597+
Note: Most elements running a [=scoped view transition=]
598+
should use [=view transition name containment=],
599+
to ensure that their [=document-scoped view transition names=]
600+
don't accidentally interfere with other [=scoped view transitions=].
601+
Otherwise, two similar elements running the same [=scoped view transition=],
602+
expecting the same-named descendants,
603+
will see each other's names and abort
604+
(since [=view transitions=] don't allow multiple elements to have the same 'view-transition-name').
605+
606+
584607
# Pseudo-elements # {#pseudo}
585608

586609
## Pseudo-element Trees ## {#pseudo-root}
@@ -609,17 +632,24 @@ spec:css2; type:dfn; text:viewport
609632
composed of the <dfn>view transition pseudo-elements</dfn> defined below.
610633
This tree is built during the [=setup transition pseudo-elements=] step,
611634
and is rooted under a ''::view-transition'' pseudo-element
612-
[=originating element|originating=] from the [=root element=].
635+
[=originating element|originating=] from the {{ViewTransition}}'s [=ViewTransition/root element=].
613636
All of the [=view transition pseudo-elements=] are selected
614-
from their [=ultimate originating element=], the [=document element=].
637+
from their [=ultimate originating element=],
638+
the {{ViewTransition}}'s [=ViewTransition/root element=].
615639

616640
The [=view transition tree=] is not exposed to the accessibility tree.
617641

618642
<div class="example">
619643
For example,
620-
the ''::view-transition-group()'' pseudo-element is attached to the root element selector directly,
621-
as in '':root::view-transition-group()'';
622-
it is not attached to its parent, the ''::view-transition'' pseudo-element.
644+
even though a ''::view-transition-group()'' pseudo-element
645+
is nested underneath its parent ''::view-transition'' pseudo-element
646+
for styling and layout purposes,
647+
it's selected directly on the element hosting the {{ViewTransition}}:
648+
if you'd use ''.foo::view-transition'',
649+
you'll also use ''.foo::view-transition-group()''.
650+
651+
Doing ''.foo::view-transition::view-transition-group()'' is incorrect,
652+
and won't select anything.
623653
</div>
624654

625655
<div class=note>
@@ -771,11 +801,34 @@ spec:css2; type:dfn; text:viewport
771801
Note: The content and [=natural dimensions=] of the image are captured in [=capture the image=],
772802
then set and updated in [=setup transition pseudo-elements=] and [=update pseudo-element styles=].
773803

804+
805+
# Scoped View Transitions # {#scoped-vt}
806+
807+
In addition to [=view transitions=] triggered on the [=document=] itself
808+
(<dfn export>global view transitions</dfn>),
809+
individual [=elements=] can host their own <dfn export>scoped view transitions</dfn>.
810+
This enables multiple [=view transitions=] to run on a page at the same time,
811+
with each animating a different subtree of the document.
812+
It also enables a [=view transition=] to be affected by the layout and rendering of its subtree,
813+
being affected by scrolling, filters, 'z-index', etc.
814+
("Global" [=view transitions=] are always rendered on a separate, higher rendering layer
815+
than the rest of the document.)
816+
817+
In order to host a [=scoped view transition=],
818+
an element must have [=layout containment=],
819+
so its painted output can be captured as an atomic unit.
820+
821+
[=View transitions=] whose [=ViewTransition/root element=] is the [=document element=]
822+
are <em>not</em> [=scoped view transitions=].
823+
They're [=global view transitions=].
824+
825+
774826
# View Transition Layout # {#view-transition-rendering}
775827

776-
The [=view transition pseudo-elements=] are styled, laid out, and rendered like normal elements,
777-
except that they originate in the [=snapshot containing block=] rather than the [=initial containing block=]
778-
and are painted in the [=view transition layer=] above the rest of the document.
828+
The [=view transition pseudo-elements=] are styled, laid out, and rendered like normal elements.
829+
[=Global view transitions=] originate in the [=snapshot containing block=] rather than the [=initial containing block=]
830+
and are painted in the [=view transition layer=] above the rest of the document;
831+
[=scoped view transitions=] are simply rendered after and above all other children of their [=ViewTransition/root element=].
779832

780833
## The Snapshot Containing Block ## {#snapshot-containing-block-concept}
781834

@@ -819,7 +872,11 @@ spec:css2; type:dfn; text:viewport
819872
to the end of the painting order established in
820873
<a href="https://www.w3.org/TR/CSS22/zindex.html">CSS2&sect;E Elaborate Description of Stacking Contexts</a>. [[!CSS2]]
821874

822-
The ''::view-transition'' pseudo-element generates a new stacking context,
875+
Issue: Fold this into [[CSS-POSITION-4]],
876+
as the interaction with [=top layers=] needs to be specified.
877+
878+
For a [=global view transition=],
879+
the ''::view-transition'' pseudo-element generates a new stacking context,
823880
called the <dfn>view transition layer</dfn>,
824881
which paints after all other content of the document
825882
(including any content rendered in the [=Document/top layer=]),
@@ -922,7 +979,7 @@ spec:css2; type:dfn; text:viewport
922979
This UA style sheet does several things:
923980
* Lay out ''::view-transition'' to cover the entire [=snapshot containing block=]
924981
so that each '':view-transition-group()'' child can lay out relative to it.
925-
* Give the [=root element=] a default [=view transition name=],
982+
* Give the [=/root element=] a default [=view transition name=],
926983
to allow it to be independently selected.
927984
* Reduce layout interference from the ''::view-transition-image-pair()'' pseudo-element
928985
so that authors can essentially treat ''::view-transition-old()'' and ''::view-transition-new()''
@@ -1527,7 +1584,7 @@ div.box {
15271584
</xmp>
15281585

15291586
<dl class="domintro non-normative">
1530-
: <code>{{ViewTransition|viewTransition}} = {{Document|document}}.{{startViewTransition}}({{ViewTransitionUpdateCallback|updateCallback}})</code>
1587+
: <code>{{ViewTransition|viewTransition}} = {{Document|document}}.{{Document/startViewTransition}}({{ViewTransitionUpdateCallback|updateCallback}})</code>
15311588
:: Starts a new [=view transition=]
15321589
(canceling the {{Document|document}}’s existing [=active view transition=], if any).
15331590

@@ -1550,42 +1607,104 @@ div.box {
15501607
<div algorithm="start-vt-with-options">
15511608
The [=method steps=] for <dfn method for=Document>startViewTransition(|callbackOptions|)</dfn> are as follows:
15521609

1553-
1. Let |updateCallback| be null.
1610+
1. Perform the {{Element}} {{Element/startViewTransition()}} [=method steps=]
1611+
given |callbackOptions|,
1612+
but for the [=/root element=],
1613+
and return the result.
1614+
</div>
15541615

1555-
1. If |callbackOptions| is a {{ViewTransitionUpdateCallback}}, set |updateCallback| to |callbackOptions|.
1616+
### {{Document/activeViewTransition}} Property ### {#doc-activeviewtransition}
15561617

1557-
1. Otherwise, if |callbackOptions| is a {{StartViewTransitionOptions}}, then set |updateCallback| to |callbackOptions|'s {{StartViewTransitionOptions/update}}.
1618+
In order to provide ergonomic behavior,
1619+
the [=active view transition=] is exposed to script via a document property.
15581620

1559-
1. If |this|'s [=active view transition=] is not null and its [=outbound post-capture steps=] is not null,
1560-
then:
1621+
<dl dfn-type=attribute dfn-for=Document>
1622+
: <dfn>activeViewTransition</dfn>
1623+
:: Returns the [=active view transition=] for the [=document=],
1624+
or null if there is no active view transition.
1625+
</dl>
1626+
1627+
Issue: Is this updated by a <code>rootEl.startViewTransition()</code> call, too?
1628+
1629+
## Additions to {{Element}} ## {#additions-to-element-api}
1630+
1631+
<xmp class=idl>
1632+
partial interface Element {
1633+
ViewTransition startViewTransition(
1634+
optional (ViewTransitionUpdateCallback or StartViewTransitionOptions) callbackOptions = {}
1635+
);
1636+
readonly attribute ViewTransition? activeViewTransition;
1637+
};
1638+
</xmp>
1639+
1640+
<dl class="domintro non-normative">
1641+
: <code>{{ViewTransition|viewTransition}} = {{Element|el}}.{{Element/startViewTransition}}({{ViewTransitionUpdateCallback|updateCallback}})</code>
1642+
:: Starts a new [=view transition=]
1643+
(potentially canceling a conflicting [=view transition=]).
1644+
1645+
{{ViewTransitionUpdateCallback|updateCallback}}, if provided, is called asynchronously, once the current state of the element and its subtree is captured.
1646+
Then, when the promise returned by {{ViewTransitionUpdateCallback|updateCallback}} fulfills,
1647+
the new state of the element and its subtree is captured
1648+
and the transition is initiated.
1649+
1650+
Note that {{ViewTransitionUpdateCallback|updateCallback}}, if provided, is *always* called,
1651+
even if the transition cannot happen
1652+
(e.g. due to duplicate `view-transition-name` values).
1653+
The transition is an enhancement around the state change, so a failure to create a transition never prevents the state change.
1654+
See [[#transitions-as-enhancements]] for more details on this principle.
1655+
1656+
If the promise returned by {{ViewTransitionUpdateCallback|updateCallback}} rejects, the transition is skipped.
1657+
</dl>
15611658

1562-
1. Let |preSkippedTransition| be a new {{ViewTransition}} in |this|'s [=relevant realm=] whose [=ViewTransition/update callback=] is |updateCallback|.
1659+
### {{Element/startViewTransition()}} Method Steps ### {#Element-ViewTransition-prepare}
15631660

1564-
Note: The |preSkippedTransition|'s {{ViewTransition/types}} are ignored here because the transition is never activated.
1661+
<div algorithm="start-el-vt-with-options">
1662+
The [=method steps=] for <dfn method for=Element>startViewTransition(|callbackOptions|)</dfn> are as follows:
15651663

1566-
1. [=Skip the view transition|Skip=] |preSkippedTransition| with an "{{InvalidStateError}}" {{DOMException}}.
1664+
1. Let |document| be [=this's=] [=relevant global object's=] [=associated document=].
1665+
1666+
1. Let |viewTransition| be a new {{ViewTransition}} object in |document|'s [=relevant Realm=],
1667+
with [=ViewTransition/root element=] set to [=this=].
1668+
1669+
1. If |callbackOptions| is a {{ViewTransitionUpdateCallback}},
1670+
set |viewTransition|'s [=update callback=] to |callbackOptions|.
1671+
1672+
Otherwise, if |callbackOptions| is a {{StartViewTransitionOptions}}, then set |viewTransition|'s [=update callback=]
1673+
to |callbackOptions|'s {{StartViewTransitionOptions/update}}.
1674+
1675+
1. If [=this=] doesn't have [=layout containment=],
1676+
[=Skip the view transition|skip=] |viewTransition| with an "{{InvalidStateError}}" {{DOMException}}, and return |viewTransition|.
15671677

1568-
1. Return |preSkippedTransition|.
1678+
1. If |document|'s [=active view transition=] is not null and its [=outbound post-capture steps=] is not null,
1679+
then:
1680+
1681+
1. [=Skip the view transition|Skip=] |viewTransition| with an "{{InvalidStateError}}" {{DOMException}}.
1682+
1683+
Note: The |viewTransition|'s {{ViewTransition/types}} are ignored here because the transition is never activated.
1684+
1685+
1. Return |viewTransition|.
15691686

15701687
Note: This ensures that a same-document transition that started after firing {{Window/pageswap}} is skipped.
15711688

1572-
1. Let |viewTransition| be the result of running the [=method steps=] for {{Document/startViewTransition(updateCallback)}} given |updateCallback|.
1689+
1. If [=this=]'s [=active view transition=] is not null,
1690+
then [=skip the view transition|skip that view transition=]
1691+
with an "{{AbortError}}" {{DOMException}} in [=this's=] [=relevant Realm=].
15731692

1574-
1. If |callbackOptions| is a {{StartViewTransitionOptions}}, set |viewTransition|'s [=ViewTransition/active types=] to a [=list/clone=] of {{StartViewTransitionOptions/types}} as a [=/set=].
1693+
Note: This can result in two asynchronous [=ViewTransition/update callbacks=] running concurrently
1694+
(and therefore possibly out of sequence):
1695+
one for the [=this=]'s current [=active view transition=], and another for this |viewTransition|.
1696+
As per the [design of this feature](#transitions-as-enhancements),
1697+
it's assumed that the developer is using another feature or framework to correctly schedule these DOM changes.
15751698

1576-
1. Return |viewTransition|.
1577-
</div>
1699+
1. Set [=this=]'s [=active view transition=] to |viewTransition|.
15781700

1579-
### {{Document/activeViewTransition}} Property ### {#doc-activeviewtransition}
1701+
Note: The [=view transition=] process continues in [=setup view transition=],
1702+
via [=perform pending transition operations=].
15801703

1581-
In order to provide ergonomic behavior,
1582-
the [=active view transition=] is exposed to script via a document property.
1704+
1. If |callbackOptions| is a {{StartViewTransitionOptions}}, set |viewTransition|'s [=ViewTransition/active types=] to a [=list/clone=] of {{StartViewTransitionOptions/types}} as a [=/set=].
15831705

1584-
<dl dfn-type=attribute dfn-for=Document>
1585-
: <dfn>activeViewTransition</dfn>
1586-
:: Returns the [=active view transition=] for the [=document=],
1587-
or null if there is no active view transition.
1588-
</dl>
1706+
1. Return |viewTransition|.
1707+
</div>
15891708

15901709
## The {{ViewTransition}} interface ## {#the-domtransition-interface}
15911710

@@ -1597,6 +1716,7 @@ the [=active view transition=] is exposed to script via a document property.
15971716
readonly attribute Promise<undefined> finished;
15981717
undefined skipTransition();
15991718
attribute ViewTransitionTypeSet types;
1719+
readonly attribute Element transitionRoot;
16001720
};
16011721
</xmp>
16021722

@@ -1646,6 +1766,12 @@ the [=active view transition=] is exposed to script via a document property.
16461766
If this is called before {{ViewTransition/ready}} resolves, {{ViewTransition/ready}} will reject.
16471767

16481768
If {{ViewTransition/finished}} hasn't resolved, it will fulfill or reject along with {{ViewTransition/updateCallbackDone}}.
1769+
1770+
: <code>{{ViewTransition|viewTransition}}.{{ViewTransition/transitionRoot}}</code>
1771+
:: The {{ViewTransition}}'s [=ViewTransition/root element=].
1772+
1773+
For [=view transitions=] started on the {{Document}},
1774+
this is the [=document element=].
16491775
</dl>
16501776

16511777
A {{ViewTransition}} has the following:
@@ -1708,6 +1834,10 @@ the [=active view transition=] is exposed to script via a document property.
17081834

17091835
: <dfn>outbound post-capture steps</dfn>
17101836
:: Null or a set of steps, initially null.
1837+
1838+
: <dfn>root element</dfn>
1839+
:: An {{Element}},
1840+
indicating which element is hosting the {{ViewTransition}}.
17111841
</dl>
17121842

17131843
The {{ViewTransition/finished}} [=getter steps=] are to return [=this's=] [=ViewTransition/finished promise=].
@@ -1718,6 +1848,8 @@ the [=active view transition=] is exposed to script via a document property.
17181848

17191849
The {{ViewTransition/types}} [=getter steps=] are to return [=this=]'s [=ViewTransition/active types=].
17201850

1851+
The {{ViewTransition/transitionRoot}} [=getter steps=] are to return [=this=]'s [=ViewTransition/root element=].
1852+
17211853
### The {{ViewTransitionTypeSet}} Interface ### {#the-viewtransitiontypeset-interface}
17221854

17231855
<xmp class=idl>
@@ -2189,11 +2321,16 @@ It has the following [=struct/items=]:
21892321
and has a [=node document=] equal to |document|,
21902322
in [paint order](https://drafts.csswg.org/css2/#painting-order):
21912323

2192-
<div class=note>We iterate in paint order to ensure that this order is cached in |namedElements|.
2193-
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.</div>
2324+
Note: We iterate in paint order to ensure that this order is cached in |namedElements|.
2325+
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.
21942326

21952327
1. If any [=flat tree=] ancestor of this |element| [=skips its contents=], then [=continue=].
21962328

2329+
1. If any [=flat tree=] [=inclusive ancestor=] of this |element|,
2330+
up to but not including |transition|'s [=ViewTransition/root element=],
2331+
has ''contain: view-transition'',
2332+
[=continue=].
2333+
21972334
1. If |element| has more than one [=box fragment=], then [=continue=].
21982335

21992336
Note: We might want to enable transitions for fragmented elements in future versions.
@@ -2214,7 +2351,13 @@ It has the following [=struct/items=]:
22142351

22152352
1. Set |element|'s [=captured in a view transition=] to false.
22162353

2217-
1. return failure.
2354+
1. Return failure.
2355+
2356+
1. If <em>any other</em> [=active view transition=] contains |element|
2357+
in its [=captured elements=],
2358+
then for each such [=active view transition=],
2359+
in [=tree order=] of their corresponding [=ViewTransition/root elements=],
2360+
[=skip the view transition|skip=] that view transition with an "{{AbortError}}" {{DOMException}} in |document|’s [=relevant Realm=].
22182361

22192362
1. [=set/Append=] |transitionName| to |usedTransitionNames|.
22202363

0 commit comments

Comments
 (0)