diff --git a/scroll-animations-1/Overview.bs b/scroll-animations-1/Overview.bs
index 28d972299e8..78c49f17046 100644
--- a/scroll-animations-1/Overview.bs
+++ b/scroll-animations-1/Overview.bs
@@ -13,9 +13,11 @@ Abstract: Defines an API and markup for creating animations that are tied to
Editor: Brian Birtles, Invited Expert, brian@birchill.co.jp, w3cid 43194
Editor: Botond Ballo, Mozilla, botond@mozilla.com
Editor: Antoine Quint, Apple, graouts@apple.com, w3cid 51377
-Editor: Majid Valipour, Google, majidvp@google.com, w3cid 81464
Editor: Olga Gerchikov, Microsoft, gerchiko@microsoft.com
+Editor: Elika J. Etemad / fantasai, Invited Expert, http://fantasai.inkedblade.net/contact, w3cid 35400
+Editor: Robert Flack, Google
+Former Editor: Majid Valipour, Google, majidvp@google.com, w3cid 81464
Former editor: Mantaroh Yoshinaga
Former editor: Stephen McGruer, Google, smcgruer@google.com
Markup Shorthands: markdown yes
@@ -37,1220 +39,560 @@ spec: cssom-view-1; type: dfn;
# Introduction # {#intro}
-This specification defines mechanisms for
-[[#scroll-driven-animations|driving the progress of an animation]] based
-on the scroll progress of a scroll container.
+ This specification defines mechanisms for
+ driving the progress of an animation
+ based on the scroll progress of a scroll container.
+ These scroll-driven animations
+ use a timeline based on scroll position,
+ rather than one based on clock time.
+ Animations are linked to such a timeline
+ using the CSS 'animation-timeline' property
+ or the Web Animations API.
+
+ [[!WEB-ANIMATIONS-1]]
+
+ There are two types of scroll-driven timelines:
+ * [=scroll progress timelines=]
+ * [=view progress timelines=]
## Relationship to other specifications ## {#other-specs}
-Web Animations [[WEB-ANIMATIONS-1]] defines an abstract conceptual model for
-animations on the Web platform, with elements of the model including
-[=animations=] and their [=timelines=],
-and associated programming interfaces.
+ Web Animations [[WEB-ANIMATIONS-1]] defines
+ an abstract conceptual model for animations on the Web platform,
+ with elements of the model including [=animations=] and their [=timelines=],
+ and associated programming interfaces.
-This specification extends this model by defining a new type of animation [=timeline=]:
-a [=scroll timeline=].
+ This specification extends this model by defining
+ a new type of animation [=timeline=]:
+ a [=scroll progress timeline=].
-This specification defines both programming interfaces for interacting with these
-concepts, as well as CSS markup which applies these concepts to CSS Animations
-[[CSS3-ANIMATIONS]].
+ This specification defines both
+ programming interfaces for interacting with these concepts,
+ as well as CSS properties which apply these concepts
+ to CSS Animations [[CSS3-ANIMATIONS]].
-The behavior of the CSS markup is described in terms of the programming interfaces.
-User agents that do not support script may still implement the CSS markup
-provided it behaves as if the underlying programming interfaces were in place.
+ The behavior of the CSS properties is described
+ in terms of the programming interfaces.
+ User agents that do not support scripting
+ may still conform to this specification
+ by implementing the CSS features to behave
+ as if the underlying programming interfaces were in place.
## Relationship to asynchronous scrolling ## {#async-scrolling}
-Some user agents support scrolling that is asynchronous with respect to layout
-or script. This specification is intended to be compatible with such an
-architecture.
+ Some user agents support scrolling that is asynchronous
+ with respect to layout or script.
+ This specification is intended to be compatible with such an architecture.
-Specifically, this specification allows expressing scroll-linked effects in a
-way that does not require script to run each time the effect is sampled. User
-agents that support asynchronous scrolling are allowed (but not required) to
-sample such effects asynchronously as well.
+ Specifically, this specification allows expressing scroll-linked effects
+ in a way that does not require script to run each time the effect is sampled.
+ User agents that support asynchronous scrolling are allowed (but not required)
+ to sample such effects asynchronously as well.
## Value Definitions ## {#values}
-This specification follows the CSS property
-definition conventions from [[!CSS2]] using the value definition
-syntax from [[!CSS-VALUES-3]]. Value types not defined in this specification
-are defined in CSS Values & Units [[!CSS-VALUES-3]]. Combination with other
-CSS modules may expand the definitions of these value types.
-
-In addition to the property-specific values listed in their definitions,
-all properties defined in this specification
-also accept the CSS-wide keywords as their property value.
-For readability they have not been repeated explicitly.
-
-# Use cases # {#use-cases}
-
-This section is non-normative
-
-Note: Based on this curated
-list of use cases.
-
-Issue(4354): These use cases need updating.
-
-## Scrollable picture-story show ## {#scrollable-animation-usecase}
-
-It is sometimes desired to use an animation to tell a story where the user
-controls the progress of the animation by scrolling or some other
-gesture. This may be because the animation contains a lot of textual
-information which the user may wish to peruse more slowly, it may be for
-accessibility considerations to accommodate users who are uncomfortable
-with rapid animation, or it may simply be to allow the user to easily
-return to previous parts of the story such as a story that introduces
-a product where the user wishes to review previous information.
-
-The following (simplified) example shows two balls colliding. The
-animation is controlled by scroll position allowing the user to easily
-rewind and replay the interaction.
-
-
-
-Using the CSS markup:
-
-
-
-## The content progress bar ## {#content-progress-bar-usecase}
-
-Another common example of an animation that tracks scroll position is a
-progress bar that is used to indicate the reader's position in a long
-article.
-
-
-
-Typically, the scroll bar provides this visual indication but
-applications may wish to hide the scroll bar for aesthetic or useability
-reasons.
-
-Using the updated 'animation' shorthand that includes 'animation-timeline',
-this example could be written as follows:
-
-
-
-The {{ScrollDirection}} enumeration specifies a direction of scroll of a
-scrollable element.
-
-
- : block
- :: Selects the direction along the [=block axis=], conforming to writing mode
- and directionality.
-
- : inline
- :: Selects the direction along the [=inline axis=], confirming to writing mode
- and directionality.
-
- : horizontal
- :: Selects the physical horizontal direction (ignoring writing mode and
- directionality).
-
- : vertical
- :: Selects the physical vertical direction (ignoring writing mode and
- directionality).
-
-
-Note: Having both logical (block/inline) and physical (vertical/horizontal)
-directions allows web developers to animate both logical (e.g.
-margin-inline-start) and physical (e.g. transform) properties with good
-behavior under different directionalities and writing modes.
-
-### The {{ScrollTimeline}} interface ### {#scrolltimeline-interface}
-
-
-
-A scroll timeline is an {{AnimationTimeline}} whose time values are
-determined not by wall-clock time, but by the progress of scrolling in a
-[=scroll container=].
-
-The {{EffectTiming/duration}} of a scroll timeline is 100%.
-
-
- : ScrollTimeline(options)
- :: Creates a new {{ScrollTimeline}} object using the following procedure:
-
- 1. Let |timeline| be a new {{ScrollTimeline}} object.
-
- 1. Let |source| be the result corresponding to the first matching condition
- from the following:
-
-
- : If the `source` member of |options| is missing,
- :: The {{Document/scrollingElement}} of the {{Document}} associated with the {{Window}} that is
- the current global object.
-
- : Otherwise,
- :: The `source` member of |options|.
-
-
- 1. Set the {{ScrollTimeline/source}} of |timeline| to |source|.
-
- 1. Assign the {{ScrollTimeline/orientation}} and
- {{ScrollTimeline/scrollOffsets}} properties of
- |timeline| to the corresponding value from |options|.
-
-
-
- : source
- :: The scrollable element whose scrolling triggers the activation and drives
- the progress of the timeline.
-
- : orientation
- :: Determines the direction of scrolling which triggers the activation and
- drives the progress of the timeline.
-
- : scrollOffsets
- :: [=Scroll timeline offsets=] which determine the [=effective scroll
- offset=]s in the direction specified by {{ScrollTimeline/orientation}} that constitute the
- equally-distanced in progress intervals in which the timeline is active.
-
- The procedure to set the offset value with |val| as the provided
- value, |pos| as the position in {{ScrollTimeline/scrollOffsets}} and |size|
- as the {{ScrollTimeline/scrollOffsets}} array size has the following steps:
-
- 1. If |val| is a {{DOMString}}, let |val| be the result of
- rectifying the keywordish value.
-
- 2. Set the offset value to be the result corresponding to the first
- matching condition from the following:
-
-
- : If |val| is a {{CSSKeywordValue}} and
- matches the grammar `auto` and |pos| equals to 0 or |size| - 1:
- :: Return |val|.
-
- : If |val| is a {{CSSNumericValue}} and
- matches the grammar <>:
- :: Return |val|.
-
- : If |val| is an {{ElementBasedOffset}}:
- :: Return |val|.
-
- : Otherwise,
- :: Do not set the value and throw a {{DOMException}} with error name
- {{SyntaxError}}.
-
-
-
-### Scroll Timeline Offset ### {#scroll-timeline-offset-section}
-
-An effective scroll offset is a scroll position for a given [=scroll
-container=] and on a given scroll direction.
-
-A scroll timeline offset is provided by authors and determines a
-[=effective scroll offset=] for the {{ScrollTimeline/source}} and in the direction specified by
-{{ScrollTimeline/orientation}}.
-
-There are two types of scroll timeline offset: [=container-based offset=], and
-[=element-based offset=]. To resolve a scroll timeline offset into an
-[=effective scroll offset=], run the procedure to [=resolve a container-based
-offset=] or to [=resolve an element-based offset=] depending on the offset type.
-It is possible for a [=scroll timeline offset=] to be resolved to null.
-
-The effective start offset is the value of first offset in
-[=effective scroll offsets=] array or null if the array is empty.
-
-The effective end offset is the value of last offset in
-[=effective scroll offsets=] array or null if the array is empty.
-
-#### Container-based Offset #### {#container-based-offset-section}
-
-A container-based offset is a scroll timeline offset that is declared
-only in relation with the scroll container as specified by {{ScrollTimeline/source}}.
-
-A [=container-based offset=] is provided in the {{CSSNumericValue}} or
-{{CSSKeywordValue}} forms.
-
-
- The procedure to resolve a container-based offset given
- |offset| and a flag is first (to indicate if the offset
- is being inserted first into [=effective scroll offsets=]) is as follows:
-
- 1. If any of the following are true:
-
- * {{ScrollTimeline/source}} is null, or
- * {{ScrollTimeline/source}} does not currently have a [=CSS layout box=], or
- * {{ScrollTimeline/source}}'s layout box is not a [=scroll container=].
-
- The [=effective scroll offset=] is null and abort remaining steps.
-
- 1. The [=effective scroll offset=] is the scroll offset corresponding to the
- first matching condition from the following:
-
-
- : If |offset| is a {{CSSKeywordValue}} and
- matches `auto`:
- :: The beginning of {{ScrollTimeline/source}}'s scroll range in {{ScrollTimeline/orientation}} if
- is first is true or the ending of {{ScrollTimeline/source}}'s scroll range in
- {{ScrollTimeline/orientation}} otherwise.
-
- : If |offset| is a {{CSSNumericValue}} and
- matches <>:
- :: The distance indicated by the value along {{ScrollTimeline/source}}'s scroll range in
- {{ScrollTimeline/orientation}} as expressed by absolute length, a percentage, or a
- ''calc()'' expression that resolves to a <>.
-
- : Otherwise,
- :: null.
-
-
-
-Note: The scroll range of an element is the range defined by its minimum and
-maximum scroll offsets which are determined by it [=scrolling box=], [=padding
-box=], and [=overflow direction=].
-
-Note: Container-based scroll offsets cannot be provided as bare numbers but
-should be {{CSSNumericValue}}. This way the full richness of {{CSSNumericValue}}
-APIs can be used to provide the offset in percentages, various length units or
-'calc()' expressions. For example `CSS.percent(50)`, `CSS.px(200)`, or
-`CSS.vh(10)` are valid and represent `50%`, `200px`, and `10vh`.
-
-Note: It is valid to provide a length or percentage based offset such that it is
-outside the source's scroll range and thus not reachable e.g., '120%'.
-
-#### Element-based Offset #### {#element-based-offset-section}
-
-An element-based offset is a scroll timeline offset that is declared
-in terms of the intersection of the scroll container as specified by
-{{ScrollTimeline/source}} and one of its descendants as specified by {{ElementBasedOffset/target}}.
-
-An [=element-based offset=] is provided in the {{ElementBasedOffset}} form.
-
-
- : target
- :: The target whose intersection with {{ScrollTimeline/source}}'s [=scrolling box=] determines
- the concrete scroll offset.
-
- : edge
- :: The edge of {{ScrollTimeline/source}}'s [=scrolling box=] in the direction specified by
- the {{ScrollTimeline/orientation}} which the target should intersect with.
-
- : threshold
- :: A double in the range of [0.0, 1.0] that represent the percentage
- of the target that is expected to be visible in {{ScrollTimeline/source}}'s [=scrollport=]
- at the intersection offset.
-
-Issue(5203): The range of the `threshold` member is not currently
-checked anywhere.
-
-
- The procedure to resolve an element-based offset given
- |offset| is as follows:
-
- 1. If any of the following are true:
-
- * {{ScrollTimeline/source}} is null, or
- * {{ScrollTimeline/source}} does not currently have a [=CSS layout box=], or
- * {{ScrollTimeline/source}}'s layout box is not a [=scroll container=].
-
- The [=effective scroll offset=] is null and abort remaining steps.
-
- 1. Let |target| be |offset|'s {{ElementBasedOffset/target}}.
-
- 1. If any of the following are true:
-
- * |target| is null, or
- * |target| does not currently have a [=CSS layout box=].
-
- The [=effective scroll offset=] is null and abort remaining steps.
-
-
- 1. If |target| 's nearest [=scroll container=] ancestor
- is not {{ScrollTimeline/source}}
- abort remaining steps
- since the [=effective scroll offset=] is null.
-
- 1. Let |container box| be the {{ScrollTimeline/source}}'s [=scrollport=].
-
- 1. Let |target box| be the result of finding
- the rectangular bounding box
- (axis-aligned in {{ScrollTimeline/source}}’s coordinate space)
- of |target|'s transformed border box.
-
- 1. If |offset|'s {{ElementBasedOffset/edge}} is "start" then
- let |scroll offset|
- be the scroll offset at which |container box|'s start edge is flush
- with the |target box|'s end edge
- in the axis and direction determined by {{ScrollTimeline/orientation}}.
-
- 1. If |offset|'s {{ElementBasedOffset/edge}} is "end" then
- let |scroll offset|
- be the scroll offset at which |container box|'s end edge is flush
- with the |target box|'s start edge
- in the axis and direction determined by {{ScrollTimeline/orientation}}.
-
- 1. Let |threshold amount| be the result of evaluating the following
- expression where |target dimension| is |target box|'s dimension in the axis
- determined by {{ScrollTimeline/orientation}}.
-
-
- 1. Clamp the value of |scroll offset| to be within the {{ScrollTimeline/source}}'s
- scroll range.
-
- 1. The [=effective scroll offset=] is |scroll offset|
-
-
-
- With threshold 0.0, the algorithm selects the effective scroll offset such
- that the target is adjacent to the [=scrollport=] at the given edge but not yet
- visible.
- The threshold value allows authors
- to control the amount of target that needs to be visible in [=scrollport=].
- In particular threshold value 1.0 ensure that target is fully visible
- (as long as [=scrollport=] is large enough).
-
-
-
-
-
- Here is a basic example showing how element-based offsets can be used to declare
- an scroll-linked animation that occurs when an element enters the scroller
- scrollport and ends once it exits the scrollport.
-
-
-
-
- Note that here we are expecting a typical top to bottom scrolling and thus
- consider the entrance to coincide when target's start edge is flushed with
- scrollport's end edge and viceversa for exit.
-
-
- if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) {
- const scrollableElement = document.querySelector('#container');
- const image = document.querySelector('#image');
-
- const timeline = new ScrollTimeline({
- source: scrollableElement,
- scrollOffsets: [{target: image, edge: 'end'},
- {target: image, edge: 'start'}],
- });
-
- const slideIn = target.animate({
- transform: ['translateX(0)', 'translateX(50vw)'],
- opacity: [0, 1]
- }, {
- timeline:timeline
- }
- );
- }
+ This specification follows the
+ CSS property definition conventions
+ from [[!CSS2]]
+ using the value definition syntax
+ from [[!CSS-VALUES-3]].
+ Value types not defined in this specification
+ are defined in CSS Values & Units [[!CSS-VALUES-3]].
+ Combination with other CSS modules may expand the definitions of these value types.
+
+ In addition to the property-specific values listed in their definitions,
+ all properties defined in this specification
+ also accept the CSS-wide keywords as their property value.
+ For readability they have not been repeated explicitly.
+
+# Scroll Progress Timelines # {#scroll-timelines}
+
+ Scroll progress timelines
+ are timelines linked to progress
+ in the scroll position of a [=scroll container=]
+ along a particular axis.
+ The startmost scroll position represents 0% progress
+ and the endmost scroll position represents 100% progress.
+ If the 0% position and 100% position coincide
+ (i.e. the [=scroll container=] has no overflow to scroll),
+ the timeline is [=timeline inactive state/inactive=].
+
+ [=Scroll progress timelines=] can be referenced in 'animation-timeline'
+ anonymously using the ''scroll()'' [=functional notation=]
+ or by name (see [[#timeline-scope]])
+ after declaring them using the 'scroll-timeline' properties.
+ In the Web Animations API,
+ they can be represented anonymously by a {{ScrollTimeline}} object.
+
+## Anonymous Scroll Progress Timelines ## {#scroll-timelines-anonymous}
+
+### The ''scroll()'' notation ### {#scroll-notation}
+
+ The ''scroll()'' functional notation
+ can be used as a value of 'animation-timeline'
+ and specifies a [=scroll progress timeline=].
+ Its syntax is
+
+
- @media (prefers-reduced-motion: no-preference) {
-
- @keyframes slide-in {
- from {
- transform: translateX(0);
- opacity: 0;
- }
-
- to {
- transform: translateX(50vw);
- opacity: 1;
- }
- }
-
- @scroll-timeline image-in-scrollport {
- source: selector(#container);
- scroll-offsets: selector(#image) end, selector(#image) start;
- }
-
- #target {
- animation-name: slide-in;
- animation-timeline: image-in-scrollport;
- }
+ By default,
+ ''scroll()'' references the [=block axis=] of the nearest ancestor [=scroll container=].
+ Its arguments modify this lookup as follows:
+
+
+
block
+
+ Specifies to use the measure of progress along the
+ [=block axis=] of the [=scroll container=].
+ (Default.)
+
+
inline
+
+ Specifies to use the measure of progress along the
+ [=inline axis=] of the [=scroll container=].
+
+
vertical
+
+ Specifies to use the measure of progress along the
+ [=vertical axis=] of the [=scroll container=].
+
+
horizontal
+
+ Specifies to use the measure of progress along the
+ [=horizontal axis=] of the [=scroll container=].
+
+
nearest
+
+ Specifies to use the nearest ancestor [=scroll container=].
+ (Default.)
+
+
root
+
+ Specifies to use the document viewport as the [=scroll container=].
+
+
<>
+
+ Specifies to use the nearest ancestor [=scroll container=]
+ that has the specified 'container-name'. [[!CSS-CONTAIN-3]]
+ If none exist, the document viewport is used.
+
- }
+### The {{ScrollTimeline}} Interface ### {#scrolltimeline-interface}
+
+
-
-### The effective scroll offsets of a {{ScrollTimeline}} ### {#effective-scroll-offsets-algorithm}
-
-
- The effective scroll offsets are calculated by the procedure to
- resolve scroll timeline offsets from {{ScrollTimeline/scrollOffsets}}
- as follows:
-
- 1. Let effective scroll offsets be an empty list of
- effective scroll offsets.
- 1. Let first offset be true.
- 1. If {{ScrollTimeline/scrollOffsets}} is empty
- 1. Run the procedure to [=resolve a scroll timeline offset=] for "auto"
- with the is first flag set to first offset and
- add the resulted value into effective scroll offsets.
- 1. Set first offset to false.
- 1. Run the procedure to [=resolve a scroll timeline offset=] for "auto"
- with the is first flag set to first offset and
- add the resulted value into effective scroll offsets.
- 1. If {{ScrollTimeline/scrollOffsets}} has exactly one element
- 1. Run the procedure to [=resolve a scroll timeline offset=] for "auto"
- with the is first flag set to first offset and
- add the resulted value into effective scroll offsets.
- 1. Set first offset to false.
- 1. For each scroll offset in the list of
- {{ScrollTimeline/scrollOffsets}}, perform the following steps:
- 1. Let effective offset be the result of applying the procedure
- to [=resolve a scroll timeline offset=] for scroll offset
- with the is first flag set to first offset.
- 1. If effective offset is null, the
- [=effective scroll offsets=] is empty and abort the remaining steps.
- 1. Add effective offset into
- effective scroll offsets.
- 1. Set first offset to false.
- 1. Return effective scroll offsets.
-
-
-### The progress of a {{ScrollTimeline}} ### {#progress-calculation-algorithm}
-
-
- The scroll timeline progress is calculated by applying the procedure
- to calculate scroll timeline progress given |offset| as follows:
-
- 1. Let scroll offsets be the result of applying the procedure to
- [=resolve scroll timeline offsets=] for {{ScrollTimeline/scrollOffsets}}.
- 1. Let offset index correspond to the position of the last offset in
- scroll offsets whose value is less than or equal to
- offset and the value at the following position greater than
- offsetstart offset be the offset value at position
- offset index in scroll offsets.
- 1. Let end offset be the value of next offset in scroll
- offsets after start offset.
- 1. Let size be the number of offsets in scroll offsets.
- 1. Let offset weight be the result of evaluating
- 1 / (size - 1).
- 1. Let interval progress be the result of evaluating
- (offset - start offset) /
- (end offset - start offset).
- 1. Return the result of evaluating
- (offset index + interval progress) ×
- offset weight.
-
- Note: This procedure guarantees that given offset belongs to
- scroll range within first and last offsets of scroll offsets.
- This is because the case when offset falls outside of the scroll
- range is handled before calling this procedure, as part of [=timeline/current time=]
- calculation.
-
- Note: The rationale behind choosing last matching offset in the array is to
- be consistent with {{findRule()}} method for finding which {{CSSKeyframeRule}}
- applies in a comma separated list of overlapping keyframes.
-
-
-### The phase of a {{ScrollTimeline}} ### {#phase-algorithm}
-
-The [=timeline phase=] of a {{ScrollTimeline}} is calculated as follows:
-
-1. If any of the following are true:
-
- * {{ScrollTimeline/source}} is null, or
- * {{ScrollTimeline/source}} does not currently have a [=CSS layout box=], or
- * {{ScrollTimeline/source}}'s layout box is not a [=scroll container=], or
- * [=effective scroll offsets=] is empty.
-
- The [=timeline phase=] is [=timeline/inactive phase|inactive=] and abort remaining steps.
-
-1. Let |current scroll offset| be the current scroll offset of
- {{ScrollTimeline/source}} in the direction specified by {{ScrollTimeline/orientation}}.
-
-1. The [=timeline phase=] is the result corresponding to the first matching condition
- from below:
-
-
- : If |current scroll offset| is less than [=effective start offset=]:
- :: The [=timeline phase=] is [=timeline/before phase|before=]
-
- : If |current scroll offset| is greater than or equal to [=effective
- end offset=] and [=effective end offset=] is less than the maximum
- scroll offset of {{ScrollTimeline/source}} in {{ScrollTimeline/orientation}}:
-
- :: The [=timeline phase=] is [=timeline/after phase|after=]
-
- Note: In web animations, in general ranges are normally exclusive of their end
- point. But there is an exception here for the scroll timeline active range as it
- may in some cases be inclusive of its end. In particular if the timeline end
- offset is the maximum scroll offset we include it in active range because it is
- not possible for user to scroll passed this point and not including this value
- in the active range would leave to animations that would not be active at the
- very last scroll position.
-
- : Otherwise,
- :: The [=timeline phase=] is [=timeline/active phase|active=].
-
-### The current time of a {{ScrollTimeline}} ### {#current-time-algorithm}
+ A {{ScrollTimeline}} is an {{AnimationTimeline}}
+ that represents a [=scroll progress timeline=].
+ It can be passed to
+ the {{Animation}} constructor or the {{Animatable/animate()}} method
+ to link the animation to a [=scroll progress timeline=].
+
+
+ : source
+ :: The [=scroll container=] element
+ whose scroll position drives the progress of the timeline.
+
+ : axis
+ :: The axis of scrolling
+ that drives the progress of the timeline.
+ See value definitions for <>, above.
+
-The [=timeline/current time=] of a {{ScrollTimeline}} is calculated as follows:
+ Inherited attributes:
+
+ : {{AnimationTimeline/currentTime}} (inherited from {{AnimationTimeline}})
+ :: Represents the scroll progress of the [=scroll container=]
+ as a percentage CSSUnitValue,
+ with 0% representing its startmost scroll position
+ (in the [=writing mode=] of the [=scroll container=]).
+ Null when the timeline is [=timeline inactive state|inactive=].
+
-1. If any of the following are true:
+ ISSUE: While 0% will usually represent the [=scroll container=]’s initial scroll position,
+ it might not depending on its [=content distribution=].
+ See [[css-align-3#overflow-scroll-position]].
+ Is this what we want?
+
- * {{ScrollTimeline/source}} is null, or
- * {{ScrollTimeline/source}} does not currently have a [=CSS layout box=], or
- * {{ScrollTimeline/source}}'s layout box is not a [=scroll container=], or
- * [=effective scroll offsets=] is empty.
+ ISSUE: Add a note about whether {{AnimationTimeline/currentTime}}
+ can be negative or > 100%.
- The [=timeline/current time=] is an unresolved time value and abort remaining steps.
+
+ : ScrollTimeline(options)
+ :: Creates a new {{ScrollTimeline}} object using the following procedure:
-1. Let |current scroll offset| be the current scroll offset of
- {{ScrollTimeline/source}} in the direction specified by {{ScrollTimeline/orientation}}.
+ 1. Let |timeline| be the new {{ScrollTimeline}} object.
-1. The [=timeline/current time=] is the result corresponding to the first matching
- condition from below:
+ 1. Set the {{ScrollTimeline/source}} of |timeline| to:
-
- : If |current scroll offset| is less than [=effective start offset=]:
- :: The [=timeline/current time=] is 0.
+
+ : If the `source` member of |options| is present and not null,
+ :: The `source` member of |options|.
- : If |current scroll offset| is greater than or equal to [=effective
- end offset=]:
- :: The [=timeline/current time=] is the {{EffectTiming/duration}}.
+ : Otherwise,
+ :: The {{Document/scrollingElement}}
+ of the {{Document}} associated
+ with the {{Window}} that is the current global object.
+
- : Otherwise,
- :: 1. Let |progress| be a result of applying
- [=calculate scroll timeline progress=] procedure for current scroll offset.
- 1. The [=timeline/current time=] is |progress| × {{EffectTiming/duration}}
+ 1. Set the {{ScrollTimeline/axis}} property of |timeline|
+ to the corresponding value from |options|.
-Note: To be considered active a scroll timeline requires its [=effective scroll
-offsets=] to be non-empty. This means that for example if one uses an
-element-based offset whose {{ElementBasedOffset/target}} is not a descendant of the scroll timeline
-{{ScrollTimeline/source}}, the timeline remains inactive.
-
-## The ''@scroll-timeline'' at-rule ## {#scroll-timeline-at-rule}
+ If the {{ScrollTimeline/source}} of a {{ScrollTimeline}}
+ is an element whose [=principal box=] does not exist
+ or is not a [=scroll container=],
+ then the {{ScrollTimeline}} is [=timeline inactive state|inactive=].
+ It is otherwise in the [=timeline active state|active=] [=timeline state=].
-[=Scroll timelines=] are specified in CSS using the @scroll-timeline
-at-rule, defined as follows:
+ A {{ScrollTimeline}}’s {{EffectTiming/duration}} is 100%.
-
-
-An ''@scroll-timeline'' rule has a name given by the <> or <> in
-its prelude. The two syntaxes are equivalent in functionality; the name is the
-value of the ident or string. As normal for <>s and <>s,
-the names are fully case-sensitive; two names are equal only if they are
-codepoint-by-codepoint equal. The <> additionally excludes the
-none keyword.
+ Scroll timelines can also be defined on the scroll container itself,
+ and then referenced by name.
+ See [[#timeline-scope]].
-Once specified, a scroll timeline may be associated with a CSS Animation
-[[CSS3-ANIMATIONS]] by using the 'animation-timeline' property.
+### Naming a Scroll Progress Timeline: the 'scroll-timeline-name' property ### {#scroll-timeline-name}
-The <> inside of ''@scroll-timeline'' rule can only contain the
-descriptors defined in this section.
-
-An ''@scroll-timeline'' rule is invalid if it occurs in a stylesheet inside of a
-[=shadow tree=], and must be ignored.
+
+ Name: scroll-timeline-name
+ Value: none | <>
+ Initial: none
+ Applies to: [=scroll containers=]
+ Inherited: no
+ Computed value: the specified keyword
+ Animation type: not animatable
+
-Issue(5167): This will likely change in the future.
+ Specifies a name for the [=scroll progress timeline=]
+ associated with this [=scroll container=].
+ The axis for this timeline is given by 'scroll-timeline-axis'.
-### Scroll Timeline descriptors ### {#scroll-timeline-descriptors}
+### Axis of a Scroll Progress Timeline: the 'scroll-timeline-axis' property ### {#scroll-timeline-axis}
+
+ Name: scroll-timeline-axis
+ Value: block | inline | vertical | horizontal
+ Initial: block
+ Applies to: [=scroll containers=]
+ Inherited: no
+ Computed value: the specified keyword
+ Animation type: not animatable
+
-
- Name: source
- For: @scroll-timeline
- Value: selector( <> ) | auto | none
- Initial: auto
-
+ Specifies an axis for the [=scroll progress timeline=]
+ associated with this [=scroll container=].
+ The name for this timeline is given by 'scroll-timeline-name'.
-'source' descriptor determines the scroll timeline's {{ScrollTimeline/source}},
-with the following values:
+ Values are as defined for ''scroll()''.
-
- : selector()
- :: The [=scroll container=] identified by the <>.
+### Scroll Timeline Shorthand: the 'scroll-timeline' shorthand ### {#scroll-timeline-shorthand}
- : auto
- :: The {{Document/scrollingElement}} of the {{Document}} associated with the {{Window}} that is the
- current global object.
+
+ A {{ViewTimeline}} is an {{AnimationTimeline}}
+ that specifies a [=view progress timeline=].
+ It can be passed to
+ the {{Animation}} constructor or the {{Animatable/animate()}} method
+ to link the animation to a [=view progress timeline=].
+
+
+ : subject
+ :: The element whose [=principal box=]’s visibility in the [=scrollport=]
+ defines the progress of the timeline.
+
+ : startOffset
+ :: Represents the starting (0% progress) scroll position
+ of the [=view progress timeline=]
+ as a length offset (in ''px'') from the scroll origin.
+ Null when the timeline is [=timeline inactive state|inactive=].
+
+ : endOffset
+ :: Represents the ending (100% progress) scroll position
+ of the [=view progress timeline=]
+ as a length offset (in ''px'') from the scroll origin.
+ Null when the timeline is [=timeline inactive state|inactive=].
+
-Issue(4338): Consider choosing animation target's nearest scrollable ancestor
-instead of document's scrolling Element for `auto`.
+ Note: The value of {{ViewTimeline/startOffset}} can be greater than {{ViewTimeline/endOffset}},
+ for example in the [=horizontal axis=] in a right-to-left (''rtl'') [=writing mode=].
-
+ ISSUE: This makes the offsets compatible with the way scrollLeft and scrollTop work,
+ which go negative from zero in RTL scroll containers,
+ is this how we want it to work here?
-'orientation' descriptor determines the scroll timeline's {{ScrollTimeline/orientation}}.
+ Inherited attributes:
-Issue: Define these values.
+
+ : {{ScrollTimeline/source}} (inherited from {{ScrollTimeline}})
+ :: The nearest ancestor of the {{ViewTimeline/subject}}
+ whose [=principal box=] establishes a [=scroll container=],
+ whose scroll position drives the progress of the timeline.
-
+ : {{ScrollTimeline/axis}} (inherited from {{ScrollTimeline}})
+ :: Specifies the axis of scrolling
+ that drives the progress of the timeline.
+ See <>, above.
-'scroll-offsets' descriptor determines the scroll timeline's {{ScrollTimeline/scrollOffsets}}.
+ : {{AnimationTimeline/currentTime}} (inherited from {{AnimationTimeline}})
+ :: Represents the current progress
+ of the [=view progress timeline=]
+ as a percentage {{CSSUnitValue}}
+ representing its [=scroll container=]’s scroll progress at that position.
+ Null when the timeline is [=timeline inactive state|inactive=].
+
-[=Scroll timeline offsets=] in CSS are represented by the
-<> type:
+
+ : ViewTimeline(options)
+ :: Creates a new {{ViewTimeline}} object using the following procedure:
-
+ 1. Let |timeline| be the new {{ViewTimeline}} object.
-The offset type depends on the value of <> per
-following:
-
-
- : If value is "auto" or of type <>
- :: The [=scroll timeline offset=] is a [=container-based offset=] with the same
- value.
-
- : If value is of type <>
- :: The [=scroll timeline offset=] is an [=element-based offset=] with the
- following member values:
- * {{ElementBasedOffset/target}} is the element identified by
- <>.
- * {{ElementBasedOffset/edge}} is the optional value of
- <>. If not provided it defaults to "start".
- * {{ElementBasedOffset/threshold}} is the optional value <>. If
- not provided it defaults to 0.
-
-
-### The CSSScrollTimelineRule Interface ### {#the-css-scroll-timeline-rule-interface}
-
-
+ 1. Set the {{ViewTimeline/subject}} and {{ScrollTimeline/axis}} properties of |timeline|
+ to the corresponding values from |options|.
-
-
name
-
- The name associated with the ''@scroll-timeline'' rule.
-
-
source
-
- The 'source' descriptor associated with the ''@scroll-timeline'', or "auto"
- if not specified.
-
-
orientation
-
- The 'orientation' descriptor associated with the ''@scroll-timeline'', or "auto" if not specified.
-
-
scrollOffsets
-
- The 'scroll-offsets' descriptor associated with the ''@scroll-timeline'', or "none" if not specified.
-
-
-
- To serialize a CSSScrollTimelineRule,
- return the concatenation of the following:
-
- 1. The string "@scroll-timeline" followed by a SPACE (U+0020).
- 1. The result of performing serialize an identifier on the rule's
- {{CSSScrollTimelineRule/name}}, followed by a SPACE (U+0020).
- 1. A single LEFT CURLY BRACKET (U+007B), followed by a SPACE (U+0020).
- 1. If the 'source' descriptor is missing, the empty string.
- Otherwise, the concatenation of the following:
- 1. The string "source:", followed by a SPACE (U+0020).
- 1. One of the following,
- depending on the value of the 'source' descriptor:
-
- 1. A single SEMICOLON (U+003B), followed by a SPACE (U+0020).
- 1. If the 'orientation' descriptor is missing, the empty string.
- Otherwise, the concatenation of the following:
- 1. The string "orientation:",
- followed by a SPACE (U+0020).
- 1. The result of performing serialize an identifier
- on the value of the 'orientation' descriptor,
- followed by a SEMICOLON (U+003B),
- followed by a SPACE (U+0020).
- 1. If the 'scroll-offsets' descriptor is missing, the empty string.
- Otherwise, the concatenation of the following:
- 1. The string "scrollOffsets:",
- followed by a SPACE (U+0020),
- followed by a LEFT SQUARE BRACKET (U+005B).
- 1. For each value in the list for the rule's 'scroll-offsets'
- descriptor:
- 1. The result of performing
- serialize a scroll timeline offset on the value.
- 1. If not the last value,
- A COMMA (U+002C), followed by a SPACE (U+0020).
- 1. A RIGHT SQUARE BRACKET (U+005D),
- followed by a SEMICOLON (U+003B),
- followed by a SPACE (U+0020).
- 1. A single RIGHT CURLY BRACKET (U+007D).
-
-
-
- To serialize a scroll timeline offset,
- return one of the following,
- depending on the value type:
-
-
- : an identifier
- : <>
- :: The result of performing serialize a CSS component value
- on that value.
- : <>
- :: The concatenation of the following:
- 1. The result of performing serialize a selector() function
- on the selector() function associated with the element offset.
- 2. If the offset has an associated {{ElementBasedOffset/edge}},
- a single SPACE (U+0020),
- followed by the result of serialize an identifier
- on the value of "edge".
- Otherwise, the empty string.
- 3. If the offset has an associated {{ElementBasedOffset/threshold}},
- a single SPACE (U+0020),
- followed by the result of serialize a CSS component value
- on the value of "threshold".
- Otherwise, the empty string.
+ 1. Set the {{ScrollTimeline/source}} of |timeline|
+ to the {{ViewTimeline/subject}}’s
+ nearest ancestor [=scroll container=] element.
-
+ If the {{ScrollTimeline/source}} or {{ViewTimeline/subject}} of a {{ViewTimeline}}
+ is an element whose [=principal box=] does not exist,
+ then the {{ViewTimeline}} is [=timeline inactive state|inactive=].
+ It is otherwise in the [=timeline active state|active=] [=timeline state=].
-
- To serialize a selector() function,
- return the concatenation of the following:
+ ISSUE: Figure out how to incorporate fit/inset abilities.
- 1. The string "selector",
- followed by LEFT PARENTHESIS (U+0028).
- 2. The result of performing serialize a selector
- on the selector() function's argument.
- 3. A single RIGHT PARENTHESIS (U+0029).
-
+## Named View Progress Timelines ## {#view-timelines-named}
-## Examples ## {#timeline-examples}
+ View timelines can also be defined declaratively
+ and then referenced by name.
+ See [[#timeline-scope]].
-
- Draw a reading progress bar along the top of the page as the user scrolls.
+### Naming a View Progress Timeline: the 'view-timeline-name' property ### {#view-timeline-name}
-
- if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) {
- let progress = document.getElementById("progress");
- let effect = new KeyframeEffect(
- progress,
- [
- { width: "0vw" },
- { width: "100vw" }
- ],
- {
- easing: "linear",
- fill: "forwards"
- });
- let timeline = new ScrollTimeline({
- source: document.documentElement,
- orientation: "vertical",
- });
- let animation = new Animation(effect, timeline);
- animation.play();
- }
-
-
-
-
- The same thing with CSS, using 'animation-timeline'.
-
-
- @media (prefers-reduced-motion: no-preference) {
-
- @scroll-timeline progress {
- /* Assume the HTML element has id 'root' */
- source: selector(#root);
- orientation: vertical;
- }
-
- @keyframes progress {
- from {
- width: 0vw;
- }
- to {
- width: 100vw;
- }
- }
-
- #progress {
- position: fixed;
- top: 0;
- width: 0;
- height: 2px;
- background-color: red;
- /* This name is used to select both the keyframes and the
- scroll-timeline at-rules. */
- animation-name: progress;
- animation-fill-mode: forwards;
- animation-timing-function: linear;
- }
-
- }
+
+ Name: view-timeline-name
+ Value: none | <>#
+ Initial: none
+ Applies to: all elements
+ Inherited: no
+ Computed value: the keyword ''view-timeline-name/none'' or a list of <>s
+ Animation type: not animatable
-
-# Avoiding cycles with layout # {#avoiding-cycles}
-
-The ability for scrolling to drive the progress of an animation, gives rise to
-the possibility of layout cycles, where a change to a scroll offset
-causes an animation's effect to update, which in turn causes a new change to the
-scroll offset.
-
-To avoid such [=layout cycles=], animations with a {{ScrollTimeline}} are
-sampled once per frame, after scrolling in response to input events has taken
-place, but before {{requestAnimationFrame()}} callbacks are run. If the sampling
-of such an animation causes a change to a scroll offset, the animation will not
-be re-sampled to reflect the new offset until the next frame.
-
-The implication of this is that in some situations, in a given frame, the
-rendered scroll offset of a scroll container may not be consistent with the state
-of an animation driven by scrolling that scroll container. However, this will
-only occur in situations where the animation's effect changes the scroll offset
-of that same scroll container (in other words, in situations where the animation's
-author is asking for trouble). In normal situations, including - importantly -
-when scrolling happens in response to input events, the rendered scroll offset
-and the state of scroll-driven animations will be consistent in each frame.
-
-User agents that composite frames asynchronously with respect to layout and/or
-script may, at their discretion, sample scroll-driven animations once per
-composited frame, rather than (or in addition to) once per full layout
-cycle. Again, if sampling such an animation causes a change to a scroll offset,
-the animation will not be re-sampled to reflect the new offset until the next
-frame.
-
-Nothing in this section is intended to require that scrolling block on layout
-or script. If a user agent normally composites frames where scrolling has
-occurred but the consequences of scrolling have not been fully propagated in
-layout or script (for example, `scroll` event listeners have not yet
-run), the user agent may likewise choose not to sample scroll-driven animations
-for that composited frame. In such cases, the rendered scroll offset and the
-state of a scroll-driven animation may be inconsistent in the composited frame.
-
-
-
Appendix A. Considerations for Security and Privacy
+ Specifies names for any [=view progress timelines=]
+ associated with this element’s [=principal box=].
-This appendix is informative.
+ Note: The number of names listed here
+ determines the number of [=view progress timelines=]
+ associated with this element.
-There are no known security or privacy impacts of this feature.
+### Axis of a View Progress Timeline: the 'view-timeline-axis' property ### {#view-timeline-axis}
-The W3C TAG is developing a
-Self-Review Questionnaire: Security and Privacy
-for editors of specifications to informatively answer.
-
-Per the Questions to Consider
-
-
-
Does this specification deal with personally-identifiable information?
-
No.
+
+ Name: view-timeline-axis
+ Value: [ block | inline | vertical | horizontal ]#
+ Initial: block
+ Applies to: all elements
+ Inherited: no
+ Computed value: a list of the keywords specified
+ Animation type: not animatable
+
-
Does this specification deal with high-value data?
-
No.
+ Specifies an axis for each named [=view progress timeline=]
+ associated with this [=scroll container=].
+
+ If 'view-timeline-name' has more names than 'view-timeline-axis' has specified axes,
+ the excess timelines use the last 'view-timeline-axis' value.
+ If 'view-timeline-name' has fewer names than 'view-timeline-axis' has specified axes,
+ the used 'view-timeline-axis' list is truncated.
+
+### Inset of a View Progress Timeline: the 'view-timeline-inset' property ### {#view-timeline-inset}
+
+
+ Name: view-timeline-inset
+ Value: [ auto | <> ]{1,4}
+ Initial: 0
+ Applies to: all elements
+ Inherited: no
+ Percentages: relative to the corresponding dimension of the relevant scrollport
+ Computed value: per side, the keyword ''view-timeline-inset/auto'' or a computed <> value
+ Animation type: by computed value type
+
-
Does this specification introduce new state for an origin that persists across browsing sessions?
-
No.
+ Specifies an inset (positive) or outset (negative) adjustment of the [=scrollport=]
+ when determining whether the box is in view
+ when setting the bounds of a [=view progress timeline=].
+ The resulting rectangle is the view progress rectangle.
-
Does this specification expose persistent, cross-origin state to the web?
-
No.
+
+
auto
+
+ Indicates to use the value of 'scroll-padding'.
-
Does this specification expose any other data to an origin that it doesn’t currently have access to?
-
No.
+
<>
+
+ Like 'scroll-padding',
+ defines an inward offset from the corresponding edge of the scrollport.
+
-
Does this specification enable new script execution/loading mechanisms?
-
No.
+ The 'view-timeline-inset' property assigns its values to each side
+ exactly as the 'margin' property does.
-
Does this specification allow an origin access to a user’s location?
-
No.
+ ISSUE: Should the initial value be zero or auto?
-
Does this specification allow an origin access to sensors on a user’s device?
-
No.
+ ISSUE: Do we need all the longhands? Seems like overkill...
-
Does this specification allow an origin access to aspects of a user’s local computing environment?
-
Does this specification allow an origin access to other devices?
-
No.
+
+ Name: view-timeline
+ Value: [ <<'view-timeline-name'>> || <<'view-timeline-axis'>> ]#
+ Applies to: all elements
+
-
Does this specification allow an origin some measure of control over a user agent’s native UI?
-
No.
+ This property is a [=shorthand=] for setting
+ 'view-timeline-name' and 'view-timeline-axis'
+ in a single declaration.
+ It does not set 'view-timeline-inset'.
-
Does this specification expose temporary identifiers to the web?
-
No.
+ ISSUE: Should it reset 'view-timeline-inset' also?
-
Does this specification distinguish between behavior in first-party and third-party contexts?
-
No.
+# Named Timeline Scoping # {#timeline-scope}
-
How should this specification work in the context of a user agent’s "incognito" mode?
-
No differently. The website should not be able to determine that the user is
- in an "incognito" mode using scroll-linked animations.
+ A named [=scroll progress timeline=] or [=view progress timeline=]
+ is referenceable in 'animation-timeline' by:
+ * the declaring element itself
+ * that element’s descendants
+ * that element’s following siblings and their descendants
-
Does this specification persist data to a user’s local device?
-
No.
+ If multiple elements have declared the same timeline name,
+ the matching timeline is the one declared
+ on the nearest element in tree order,
+ which considers siblings closer than parents.
+ In case of a name conflict on the same element,
+ [=scroll progress timelines=] take precedence over [=view progress timelines=].
-
Does this specification have a "Security Considerations" and "Privacy Considerations" section?
-
Yes.
+ ISSUE: Do we want to expand this scope to preceding siblings and/or distant cousins?
-
Does this specification allow downgrading default security characteristics?
-
No.
-
+# Avoiding cycles with layout # {#avoiding-cycles}
+ The ability for scrolling to drive the progress of an animation,
+ gives rise to the possibility of layout cycles,
+ where a change to a scroll offset causes an animation's effect to update,
+ which in turn causes a new change to the scroll offset.
+
+ To avoid such [=layout cycles=],
+ animations with a [=scroll progress timeline=] are sampled once per frame,
+ after scrolling in response to input events has taken place,
+ but before {{requestAnimationFrame()}} callbacks are run.
+ If the sampling of such an animation causes a change to a scroll offset,
+ the animation will not be re-sampled to reflect the new offset
+ until the next frame.
+
+ The implication of this is that in some situations, in a given frame,
+ the rendered scroll offset of a scroll container might not be consistent
+ with the state of an animation driven by scrolling that scroll container.
+ However, this will only occur in situations where the animation's effect
+ changes the scroll offset of that same scroll container
+ (in other words, in situations where the animation's author is asking for trouble).
+ In normal situations, including—importantly--
+ when scrolling happens in response to input events,
+ the rendered scroll offset and the state of scroll-driven animations
+ will be consistent in each frame.
+
+ User agents that composite frames asynchronously
+ with respect to layout and/or script
+ may, at their discretion, sample scroll-driven animations
+ once per composited frame,
+ rather than (or in addition to) once per full layout cycle.
+ Again, if sampling such an animation causes a change to a scroll offset,
+ the animation will not be re-sampled to reflect the new offset
+ until the next frame.
+
+ Nothing in this section is intended to require
+ that scrolling block on layout or script.
+ If a user agent normally composites frames where scrolling has occurred
+ but the consequences of scrolling have not been fully propagated in layout or script
+ (for example, `scroll` event listeners have not yet run),
+ the user agent may likewise choose not to sample scroll-driven animations
+ for that composited frame.
+ In such cases, the rendered scroll offset
+ and the state of a scroll-driven animation
+ may be inconsistent in the composited frame.
diff --git a/scroll-animations-1/rewrite.bs b/scroll-animations-1/rewrite.bs
deleted file mode 100644
index 78c49f17046..00000000000
--- a/scroll-animations-1/rewrite.bs
+++ /dev/null
@@ -1,598 +0,0 @@
-
-Title: Scroll-linked Animations
-Group: CSSWG
-Status: ED
-Work Status: exploring
-Level: 1
-Group: CSSWG
-URL: https://drafts.csswg.org/scroll-animations-1/
-ED: https://drafts.csswg.org/scroll-animations-1/
-Shortname: scroll-animations-1
-Abstract: Defines an API and markup for creating animations that are tied to
- the scroll offset of a scroll container.
-Editor: Brian Birtles, Invited Expert, brian@birchill.co.jp, w3cid 43194
-Editor: Botond Ballo, Mozilla, botond@mozilla.com
-Editor: Antoine Quint, Apple, graouts@apple.com, w3cid 51377
-Editor: Olga Gerchikov, Microsoft, gerchiko@microsoft.com
-Editor: Elika J. Etemad / fantasai, Invited Expert, http://fantasai.inkedblade.net/contact, w3cid 35400
-Editor: Robert Flack, Google
-
-Former Editor: Majid Valipour, Google, majidvp@google.com, w3cid 81464
-Former editor: Mantaroh Yoshinaga
-Former editor: Stephen McGruer, Google, smcgruer@google.com
-Markup Shorthands: markdown yes
-
-
-urlPrefix: https://html.spec.whatwg.org/multipage/browsers.html#concept-document-window; type: dfn; spec: html
- text: document associated with a window; url: concept-document-window
-
-
-
-
-# Introduction # {#intro}
-
- This specification defines mechanisms for
- driving the progress of an animation
- based on the scroll progress of a scroll container.
- These scroll-driven animations
- use a timeline based on scroll position,
- rather than one based on clock time.
- Animations are linked to such a timeline
- using the CSS 'animation-timeline' property
- or the Web Animations API.
-
- [[!WEB-ANIMATIONS-1]]
-
- There are two types of scroll-driven timelines:
- * [=scroll progress timelines=]
- * [=view progress timelines=]
-
-## Relationship to other specifications ## {#other-specs}
-
- Web Animations [[WEB-ANIMATIONS-1]] defines
- an abstract conceptual model for animations on the Web platform,
- with elements of the model including [=animations=] and their [=timelines=],
- and associated programming interfaces.
-
- This specification extends this model by defining
- a new type of animation [=timeline=]:
- a [=scroll progress timeline=].
-
- This specification defines both
- programming interfaces for interacting with these concepts,
- as well as CSS properties which apply these concepts
- to CSS Animations [[CSS3-ANIMATIONS]].
-
- The behavior of the CSS properties is described
- in terms of the programming interfaces.
- User agents that do not support scripting
- may still conform to this specification
- by implementing the CSS features to behave
- as if the underlying programming interfaces were in place.
-
-## Relationship to asynchronous scrolling ## {#async-scrolling}
-
- Some user agents support scrolling that is asynchronous
- with respect to layout or script.
- This specification is intended to be compatible with such an architecture.
-
- Specifically, this specification allows expressing scroll-linked effects
- in a way that does not require script to run each time the effect is sampled.
- User agents that support asynchronous scrolling are allowed (but not required)
- to sample such effects asynchronously as well.
-
-## Value Definitions ## {#values}
-
- This specification follows the
- CSS property definition conventions
- from [[!CSS2]]
- using the value definition syntax
- from [[!CSS-VALUES-3]].
- Value types not defined in this specification
- are defined in CSS Values & Units [[!CSS-VALUES-3]].
- Combination with other CSS modules may expand the definitions of these value types.
-
- In addition to the property-specific values listed in their definitions,
- all properties defined in this specification
- also accept the CSS-wide keywords as their property value.
- For readability they have not been repeated explicitly.
-
-# Scroll Progress Timelines # {#scroll-timelines}
-
- Scroll progress timelines
- are timelines linked to progress
- in the scroll position of a [=scroll container=]
- along a particular axis.
- The startmost scroll position represents 0% progress
- and the endmost scroll position represents 100% progress.
- If the 0% position and 100% position coincide
- (i.e. the [=scroll container=] has no overflow to scroll),
- the timeline is [=timeline inactive state/inactive=].
-
- [=Scroll progress timelines=] can be referenced in 'animation-timeline'
- anonymously using the ''scroll()'' [=functional notation=]
- or by name (see [[#timeline-scope]])
- after declaring them using the 'scroll-timeline' properties.
- In the Web Animations API,
- they can be represented anonymously by a {{ScrollTimeline}} object.
-
-## Anonymous Scroll Progress Timelines ## {#scroll-timelines-anonymous}
-
-### The ''scroll()'' notation ### {#scroll-notation}
-
- The ''scroll()'' functional notation
- can be used as a value of 'animation-timeline'
- and specifies a [=scroll progress timeline=].
- Its syntax is
-
-
-
- By default,
- ''scroll()'' references the [=block axis=] of the nearest ancestor [=scroll container=].
- Its arguments modify this lookup as follows:
-
-
-
block
-
- Specifies to use the measure of progress along the
- [=block axis=] of the [=scroll container=].
- (Default.)
-
-
inline
-
- Specifies to use the measure of progress along the
- [=inline axis=] of the [=scroll container=].
-
-
vertical
-
- Specifies to use the measure of progress along the
- [=vertical axis=] of the [=scroll container=].
-
-
horizontal
-
- Specifies to use the measure of progress along the
- [=horizontal axis=] of the [=scroll container=].
-
-
nearest
-
- Specifies to use the nearest ancestor [=scroll container=].
- (Default.)
-
-
root
-
- Specifies to use the document viewport as the [=scroll container=].
-
-
<>
-
- Specifies to use the nearest ancestor [=scroll container=]
- that has the specified 'container-name'. [[!CSS-CONTAIN-3]]
- If none exist, the document viewport is used.
-
-
-### The {{ScrollTimeline}} Interface ### {#scrolltimeline-interface}
-
-
-
- A {{ScrollTimeline}} is an {{AnimationTimeline}}
- that represents a [=scroll progress timeline=].
- It can be passed to
- the {{Animation}} constructor or the {{Animatable/animate()}} method
- to link the animation to a [=scroll progress timeline=].
-
-
- : source
- :: The [=scroll container=] element
- whose scroll position drives the progress of the timeline.
-
- : axis
- :: The axis of scrolling
- that drives the progress of the timeline.
- See value definitions for <>, above.
-
-
- Inherited attributes:
-
- : {{AnimationTimeline/currentTime}} (inherited from {{AnimationTimeline}})
- :: Represents the scroll progress of the [=scroll container=]
- as a percentage CSSUnitValue,
- with 0% representing its startmost scroll position
- (in the [=writing mode=] of the [=scroll container=]).
- Null when the timeline is [=timeline inactive state|inactive=].
-
-
- ISSUE: While 0% will usually represent the [=scroll container=]’s initial scroll position,
- it might not depending on its [=content distribution=].
- See [[css-align-3#overflow-scroll-position]].
- Is this what we want?
-
-
- ISSUE: Add a note about whether {{AnimationTimeline/currentTime}}
- can be negative or > 100%.
-
-
- : ScrollTimeline(options)
- :: Creates a new {{ScrollTimeline}} object using the following procedure:
-
- 1. Let |timeline| be the new {{ScrollTimeline}} object.
-
- 1. Set the {{ScrollTimeline/source}} of |timeline| to:
-
-
- : If the `source` member of |options| is present and not null,
- :: The `source` member of |options|.
-
- : Otherwise,
- :: The {{Document/scrollingElement}}
- of the {{Document}} associated
- with the {{Window}} that is the current global object.
-
-
- 1. Set the {{ScrollTimeline/axis}} property of |timeline|
- to the corresponding value from |options|.
-
-
- If the {{ScrollTimeline/source}} of a {{ScrollTimeline}}
- is an element whose [=principal box=] does not exist
- or is not a [=scroll container=],
- then the {{ScrollTimeline}} is [=timeline inactive state|inactive=].
- It is otherwise in the [=timeline active state|active=] [=timeline state=].
-
- A {{ScrollTimeline}}’s {{EffectTiming/duration}} is 100%.
-
-## Named Scroll Progress Timelines ## {#scroll-timelines-named}
-
- Scroll timelines can also be defined on the scroll container itself,
- and then referenced by name.
- See [[#timeline-scope]].
-
-### Naming a Scroll Progress Timeline: the 'scroll-timeline-name' property ### {#scroll-timeline-name}
-
-
- Name: scroll-timeline-name
- Value: none | <>
- Initial: none
- Applies to: [=scroll containers=]
- Inherited: no
- Computed value: the specified keyword
- Animation type: not animatable
-
-
- Specifies a name for the [=scroll progress timeline=]
- associated with this [=scroll container=].
- The axis for this timeline is given by 'scroll-timeline-axis'.
-
-### Axis of a Scroll Progress Timeline: the 'scroll-timeline-axis' property ### {#scroll-timeline-axis}
-
-
- Name: scroll-timeline-axis
- Value: block | inline | vertical | horizontal
- Initial: block
- Applies to: [=scroll containers=]
- Inherited: no
- Computed value: the specified keyword
- Animation type: not animatable
-
-
- Specifies an axis for the [=scroll progress timeline=]
- associated with this [=scroll container=].
- The name for this timeline is given by 'scroll-timeline-name'.
-
- Values are as defined for ''scroll()''.
-
-### Scroll Timeline Shorthand: the 'scroll-timeline' shorthand ### {#scroll-timeline-shorthand}
-
-
- Name: scroll-timeline
- Value: <<'scroll-timeline-axis'>> || <<'scroll-timeline-name'>>
- Applies to: [=scroll containers=]
- Inherited: no
- Animation type: not animatable
-
-
- This property is a [=shorthand=] for setting
- 'scroll-timeline-name' and 'scroll-timeline-axis'
- in a single declaration.
-
-# View Progress Timelines # {#view-timelines}
-
- Often animations are desired to start and end
- during the portion of the [=scroll progress timeline=]
- that a particular element
- (the view progress subject element)
- is in view within the [=scrollport=].
- View progress timelines
- are segments of a [=scroll progress timeline=]
- that are scoped to the scroll positions
- in which the associated element’s [=principal box=]
- intersects its nearest ancestor [=scrollport=].
- The startmost such scroll position represents 0% progress
- and the endmost such scroll position represents 100% progress.
-
- [=View progress timelines=] can be referenced in 'animation-timeline' by name
- (see [[#timeline-scope]])
- after declaring them using the 'view-timeline' properties
- on the view progress subject.
- In the Web Animations API,
- they can be represented anonymously by a {{ViewTimeline}} object.
-
-## Anonymous View Progress Timelines ## {#view-timelines-anonymous}
-
-### The {{ViewTimeline}} Interface ### {#viewtimeline-interface}
-
-
-
- A {{ViewTimeline}} is an {{AnimationTimeline}}
- that specifies a [=view progress timeline=].
- It can be passed to
- the {{Animation}} constructor or the {{Animatable/animate()}} method
- to link the animation to a [=view progress timeline=].
-
-
- : subject
- :: The element whose [=principal box=]’s visibility in the [=scrollport=]
- defines the progress of the timeline.
-
- : startOffset
- :: Represents the starting (0% progress) scroll position
- of the [=view progress timeline=]
- as a length offset (in ''px'') from the scroll origin.
- Null when the timeline is [=timeline inactive state|inactive=].
-
- : endOffset
- :: Represents the ending (100% progress) scroll position
- of the [=view progress timeline=]
- as a length offset (in ''px'') from the scroll origin.
- Null when the timeline is [=timeline inactive state|inactive=].
-
-
- Note: The value of {{ViewTimeline/startOffset}} can be greater than {{ViewTimeline/endOffset}},
- for example in the [=horizontal axis=] in a right-to-left (''rtl'') [=writing mode=].
-
- ISSUE: This makes the offsets compatible with the way scrollLeft and scrollTop work,
- which go negative from zero in RTL scroll containers,
- is this how we want it to work here?
-
- Inherited attributes:
-
-
- : {{ScrollTimeline/source}} (inherited from {{ScrollTimeline}})
- :: The nearest ancestor of the {{ViewTimeline/subject}}
- whose [=principal box=] establishes a [=scroll container=],
- whose scroll position drives the progress of the timeline.
-
- : {{ScrollTimeline/axis}} (inherited from {{ScrollTimeline}})
- :: Specifies the axis of scrolling
- that drives the progress of the timeline.
- See <>, above.
-
- : {{AnimationTimeline/currentTime}} (inherited from {{AnimationTimeline}})
- :: Represents the current progress
- of the [=view progress timeline=]
- as a percentage {{CSSUnitValue}}
- representing its [=scroll container=]’s scroll progress at that position.
- Null when the timeline is [=timeline inactive state|inactive=].
-
-
-
- : ViewTimeline(options)
- :: Creates a new {{ViewTimeline}} object using the following procedure:
-
- 1. Let |timeline| be the new {{ViewTimeline}} object.
-
- 1. Set the {{ViewTimeline/subject}} and {{ScrollTimeline/axis}} properties of |timeline|
- to the corresponding values from |options|.
-
- 1. Set the {{ScrollTimeline/source}} of |timeline|
- to the {{ViewTimeline/subject}}’s
- nearest ancestor [=scroll container=] element.
-
-
- If the {{ScrollTimeline/source}} or {{ViewTimeline/subject}} of a {{ViewTimeline}}
- is an element whose [=principal box=] does not exist,
- then the {{ViewTimeline}} is [=timeline inactive state|inactive=].
- It is otherwise in the [=timeline active state|active=] [=timeline state=].
-
- ISSUE: Figure out how to incorporate fit/inset abilities.
-
-## Named View Progress Timelines ## {#view-timelines-named}
-
- View timelines can also be defined declaratively
- and then referenced by name.
- See [[#timeline-scope]].
-
-### Naming a View Progress Timeline: the 'view-timeline-name' property ### {#view-timeline-name}
-
-
- Name: view-timeline-name
- Value: none | <>#
- Initial: none
- Applies to: all elements
- Inherited: no
- Computed value: the keyword ''view-timeline-name/none'' or a list of <>s
- Animation type: not animatable
-
-
- Specifies names for any [=view progress timelines=]
- associated with this element’s [=principal box=].
-
- Note: The number of names listed here
- determines the number of [=view progress timelines=]
- associated with this element.
-
-### Axis of a View Progress Timeline: the 'view-timeline-axis' property ### {#view-timeline-axis}
-
-
- Name: view-timeline-axis
- Value: [ block | inline | vertical | horizontal ]#
- Initial: block
- Applies to: all elements
- Inherited: no
- Computed value: a list of the keywords specified
- Animation type: not animatable
-
-
- Specifies an axis for each named [=view progress timeline=]
- associated with this [=scroll container=].
-
- If 'view-timeline-name' has more names than 'view-timeline-axis' has specified axes,
- the excess timelines use the last 'view-timeline-axis' value.
- If 'view-timeline-name' has fewer names than 'view-timeline-axis' has specified axes,
- the used 'view-timeline-axis' list is truncated.
-
-### Inset of a View Progress Timeline: the 'view-timeline-inset' property ### {#view-timeline-inset}
-
-
- Name: view-timeline-inset
- Value: [ auto | <> ]{1,4}
- Initial: 0
- Applies to: all elements
- Inherited: no
- Percentages: relative to the corresponding dimension of the relevant scrollport
- Computed value: per side, the keyword ''view-timeline-inset/auto'' or a computed <> value
- Animation type: by computed value type
-
-
- Specifies an inset (positive) or outset (negative) adjustment of the [=scrollport=]
- when determining whether the box is in view
- when setting the bounds of a [=view progress timeline=].
- The resulting rectangle is the view progress rectangle.
-
-
-
auto
-
- Indicates to use the value of 'scroll-padding'.
-
-
<>
-
- Like 'scroll-padding',
- defines an inward offset from the corresponding edge of the scrollport.
-
-
- The 'view-timeline-inset' property assigns its values to each side
- exactly as the 'margin' property does.
-
- ISSUE: Should the initial value be zero or auto?
-
- ISSUE: Do we need all the longhands? Seems like overkill...
-
-### View Timeline Shorthand: the 'view-timeline' shorthand ### {#view-timeline-shorthand}
-
-
- Name: view-timeline
- Value: [ <<'view-timeline-name'>> || <<'view-timeline-axis'>> ]#
- Applies to: all elements
-
-
- This property is a [=shorthand=] for setting
- 'view-timeline-name' and 'view-timeline-axis'
- in a single declaration.
- It does not set 'view-timeline-inset'.
-
- ISSUE: Should it reset 'view-timeline-inset' also?
-
-# Named Timeline Scoping # {#timeline-scope}
-
- A named [=scroll progress timeline=] or [=view progress timeline=]
- is referenceable in 'animation-timeline' by:
- * the declaring element itself
- * that element’s descendants
- * that element’s following siblings and their descendants
-
- If multiple elements have declared the same timeline name,
- the matching timeline is the one declared
- on the nearest element in tree order,
- which considers siblings closer than parents.
- In case of a name conflict on the same element,
- [=scroll progress timelines=] take precedence over [=view progress timelines=].
-
- ISSUE: Do we want to expand this scope to preceding siblings and/or distant cousins?
-
-# Avoiding cycles with layout # {#avoiding-cycles}
-
- The ability for scrolling to drive the progress of an animation,
- gives rise to the possibility of layout cycles,
- where a change to a scroll offset causes an animation's effect to update,
- which in turn causes a new change to the scroll offset.
-
- To avoid such [=layout cycles=],
- animations with a [=scroll progress timeline=] are sampled once per frame,
- after scrolling in response to input events has taken place,
- but before {{requestAnimationFrame()}} callbacks are run.
- If the sampling of such an animation causes a change to a scroll offset,
- the animation will not be re-sampled to reflect the new offset
- until the next frame.
-
- The implication of this is that in some situations, in a given frame,
- the rendered scroll offset of a scroll container might not be consistent
- with the state of an animation driven by scrolling that scroll container.
- However, this will only occur in situations where the animation's effect
- changes the scroll offset of that same scroll container
- (in other words, in situations where the animation's author is asking for trouble).
- In normal situations, including—importantly--
- when scrolling happens in response to input events,
- the rendered scroll offset and the state of scroll-driven animations
- will be consistent in each frame.
-
- User agents that composite frames asynchronously
- with respect to layout and/or script
- may, at their discretion, sample scroll-driven animations
- once per composited frame,
- rather than (or in addition to) once per full layout cycle.
- Again, if sampling such an animation causes a change to a scroll offset,
- the animation will not be re-sampled to reflect the new offset
- until the next frame.
-
- Nothing in this section is intended to require
- that scrolling block on layout or script.
- If a user agent normally composites frames where scrolling has occurred
- but the consequences of scrolling have not been fully propagated in layout or script
- (for example, `scroll` event listeners have not yet run),
- the user agent may likewise choose not to sample scroll-driven animations
- for that composited frame.
- In such cases, the rendered scroll offset
- and the state of a scroll-driven animation
- may be inconsistent in the composited frame.