From 2bbc2d7c29853cf8ff9da69d8ddc03af15f2ca75 Mon Sep 17 00:00:00 2001 From: andruud Date: Fri, 6 Mar 2026 14:38:05 +0100 Subject: [PATCH] [scroll-animations-1] Make timeline name scoping last-in-tree-order See #12581, #13364. --- scroll-animations-1/Overview.bs | 240 ++++++++++++++++++++++---------- 1 file changed, 169 insertions(+), 71 deletions(-) diff --git a/scroll-animations-1/Overview.bs b/scroll-animations-1/Overview.bs index cd7879ca811c..7321c000a2bc 100644 --- a/scroll-animations-1/Overview.bs +++ b/scroll-animations-1/Overview.bs @@ -534,6 +534,9 @@ spec:selectors-4; type:dfn; text:selector Specifies names for the [=named scroll progress timelines=] associated with this element. + Makes this element a [=weak timeline scope=] + for the specified names. + ### Axis of a Scroll Progress Timeline: the 'scroll-timeline-axis' property ### {#scroll-timeline-axis}
@@ -980,6 +983,9 @@ spec:selectors-4; type:dfn; text:selector
 	Specifies names for the [=named view progress timelines=]
 	associated with this element.
 
+	Makes this element a [=weak timeline scope=]
+	for the specified names.
+
 ### Axis of a View Progress Timeline: the 'view-timeline-axis' property ### {#view-timeline-axis}
 
 	
@@ -1096,19 +1102,16 @@ spec:selectors-4; type:dfn; text:selector
 	any real use cases for multiple iterations here.
 
 ## Named Timeline Scoping and Lookup ## {#timeline-scoping}
+	
+	Named [=scroll progress timelines=] and [=view progress timelines=]
+	are referenceable within the subtree of a [=timeline scope=],
+	with the [=document element=] itself acting as an implicit default scope.
 
-	A named [=scroll progress timeline=] or [=view progress timeline=]
-	is referenceable by:
-	* the name-declaring element itself
-	* that element’s descendants
-
-	Note: The 'timeline-scope' property can be used
-	to declare the name of a timeline on an ancestor of its defining element,
-	effectively expanding its scope beyond that element’s subtree.
+	When there are multiple competing definitions
+	for the same name within the subtree of a [=timeline scope=],
+	the definition provided by the last element in [=flat tree=] order
+	takes precedence.
 
-	If multiple elements have declared the same timeline name,
-	the matching timeline is the one declared
-	on the nearest element in tree order.
 	In case of a name conflict on the same element,
 	names declared later in the naming property
 	('scroll-timeline-name', 'view-timeline-name')
@@ -1116,42 +1119,69 @@ spec:selectors-4; type:dfn; text:selector
 	[=scroll progress timelines=] take precedence over [=view progress timelines=].
 
 	
- Using ''timeline-scope'', - an element can refer to timelines - bound to elements that are siblings, cousins, or even descendants. - For example, the following creates an animation on an element - that is linked to a [=scroll progress timeline=] - defined by the subsequent sibling. - - - <style> - @keyframes anim { - from { color: red; } - to { color: green; } - } + Say you have multiple instances of a component, + each defining a timeline + and some element using that timeline: - .root { - /* declares the scope of a '--scroller' timeline to reach all descendants */ - timeline-scope: --scroller; - } + ```html + <div> + <div class="component"> + <div style="view-timeline: --v /*...*/;"></div> + <div style="animation-timeline: --v;"></div> + </div> + <div class="component"> + <div style="view-timeline: --v /*...*/;"></div> + <div style="animation-timeline: --v;"></div> + </div> + </div> + ``` - .root .animation { - animation: anim; - /* references the '--scroller' timeline for driving the progress of 'anim' */ - animation-timeline: --scroller; - } + The problem with this is that multiple definitions of `--v` + exist in the same [=timeline scope=]; + both instances of `animation-timeline:--v` + find the *same* timeline, + i.e. the last one seen in [=flat tree=] order. - .root .animation + .scroller { - /* attaches a scroll progress timeline to the timeline named '--scroller' */ - scroll-timeline: --scroller; - } + We can fix this by making the component elements [=timeline scopes=] + for `--v`: + + ```html + <style> + .component { + timeline-scope: --v; + } </style> - &hellip; - <section class="root"> - <div class="animation">Animating Box</div> - <div class="scroller">Scrollable Box</div> - </section> - + ``` + + Now, any lookup of `--v` taking place within a component + will only see timelines defined by the component. + +
+ +
+ Within a [=timeline scope=], + a named timeline can be referenced from any element in the same scope, + either before or after the timeline-providing element in tree-order. + + ```html +
+
+
+
+
+ ``` + + In the above example, + both instances of `animation-timeline:--t` find the same [=scroll progress timeline=] + named `--t`. + + You can also reach `--t` from the timeline-providing element itself, + though this lookup would technically take place + in a separate [=weak timeline scope=]: + + ```html +
+ ```
## Animation Events ## {#events} @@ -1665,7 +1695,11 @@ spec:selectors-4; type:dfn; text:selector which allows declaring a timeline name’s scope on an ancestor of the timeline’s defining element. -## Declaring a Named Timeline’s Scope: the 'timeline-scope' property ## {#timeline-scope} +## Declaring a Named Timeline’s Scope: the 'timeline-scope' property ## {#timeline-scope-property} + + The 'timeline-scope' property + makes an element a [=strong timeline scope=] + for the specified timeline names.
 		Name: timeline-scope
@@ -1673,50 +1707,111 @@ spec:selectors-4; type:dfn; text:selector
 		Initial: none
 		Applies to: all elements
 		Inherited: no
-		Computed value: the keyword ''timeline-scope/none'' or a list of [=CSS identifiers=]
+		Computed value: the keyword ''timeline-scope/none'',
+			the keyword ''timeline-scope/all'',
+			or a list of [=CSS identifiers=]
 		Animation type: not animatable
 	
- This property declares the scope of the specified timeline names - to extend across this element’s subtree. - This allows a named timeline - (such as a [=named scroll progress timeline=] or [=named view progress timeline=]) - to be referenced by elements outside the timeline-defining element’s subtree-- - for example, by siblings, cousins, or ancestors. - It also blocks descendant timelines with the specified names - from being referenced from outside this subtree, - and ancestor timelines with the specified names from being referenced - within this subtree. - - ISSUE(8915): There's some open discussion about these blocking effects. - Values have the following meanings:
none
- No changes in timeline name scope. + The element is not a [=strong timeline scope=] for any name.
all
- Declares the names of all timelines defined by descendants-- - whose scope is not already explicitly declared by a descendant using 'timeline-scope'-- - to be in scope for this element and its descendants. + The element is a [=strong timeline scope=] + for *all* timeline names.
<>
- Declares the name of a matching named timeline defined by a descendant-- - whose scope is not already explicitly declared by a descendant using 'timeline-scope'-- - to be in scope for this element and its descendants. + The element is a [=strong timeline scope=] + for the specified names only. +
+ + A timeline scope is an element which limits the visibility + of named timelines within the inclusive [=flat tree=] descendants of that element. + A reference to a named timeline + from an element within the subtree of a [=timeline scope=] + can only find timeline definitions provided by elements in the same subtree. - If no such timeline exists, - or if more than one such timeline exists, - instead declares an [=inactive timeline=] with the specified name. + Elements that are [=timeline scopes=] + can either be [=strong timeline scopes=], + or [=weak timeline scopes=]: + +
+
strong timeline scope
+
+ Named timelines defined on the [=timeline scope=] element + or any of its [=flat tree=] descendants + are only visible within that subtree. + +
+ ```html +
+ +
+
+ +
+ ``` + Note that `animation-timeline:--t` on `#e` itself + (the [=timeline scope=]) would also find `--t`; + `#e` counts as being *inside* the scope. +
+ +
+ +
weak timeline scope
+
+ Acts like a [=strong timeline scope=], + except that timelines defined on the [=timeline scope=] element itself + are also visible on the outside + of the subtree. + + Note: Lookups from an element that is a [=weak timeline scope=] + are still subject to visibility restrictions; + if that element defines a timeline `--t`, + then `animation-timeline:--t` on the same element + always refers to that timeline. + +
+ Using 'scroll-timeline' on an element + makes it a [=weak timeline scope=]: + + ```html +
+ +
+
+ +
+ ``` + + Had we defined a second timeline + in the outer scope + on an element appearing after `#e` in [=flat tree=] order, + the outer reference would now see that timeline instead: + + ```html +
+ +
+
+ +
+
+ ``` +
+
- Note: This property cannot affect or invalidate any timeline name lookups - within the subtree of a descendant element that declares the same name. - See [[#timeline-scope]]. + When an element is both a [=strong timeline scope=] + and a [=weak timeline scope=] for the same name, + it behaves like a [=strong timeline scope=] for that name. # Changes # {#changes} @@ -1724,6 +1819,9 @@ spec:selectors-4; type:dfn; text:selector (28 April 2023) Working Draft include: + * Changed timeline name scoping to use nearest-ancestor and last-in-tree-order resolution. + (Issue 12581), + (Issue 13364) * Allow ''all'' as a value for 'timeline-scope'. (Issue 9158) * Removed scroll-timeline-attachment and view-timeline-attachment in favor of 'timeline-scope'.