1. Introduction
This specification defines mechanisms for driving the progress of an animation based on the scroll progress of a scroll container.
1.1. Relationship to other specifications
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 defines both programming interfaces for interacting with these concepts, as well as CSS markup which applies 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.
1.2. Relationship to asynchronous 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.
1.3. Value Definitions
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.
2. Use cases
This section is non-normative
Note: Based on this curated list of use cases.
These use cases need updating. [Issue #4354]
2.1. Scrollable picture-story show
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.
The left figure shows the initial position of the balls.
The right figure shows them after they have collided.
Using the CSS markup:
@media ( prefers-reduced-motion: no-preference) { div.circle{ animation-timing-function : linear; animation-timeline : collision-timeline; } #left-circle{ animation-name : left-circle; } #right-circle{ animation-name : right-circle; } #union-circle{ animation-name : union-circle; animation-fill-mode : forwards; animation-timeline : union-timeline; } @scroll-timeline collision-timeline{ source : selector ( #container); orientation : block; scroll-offsets : 200 px , 300 px ; } @scroll-timeline union-timeline{ source : selector ( #container); orientation : block; scroll-offsets : 250 px , 300 px ; } @keyframes left-circle{ to{ transform : translate ( 300 px ) } } @keyframes right-circle{ to{ transform : translate ( 350 px ) } } @keyframes union-circle{ to{ opacity : 1 } } }
Using the programming interface, we might write this as:
if ( window. matchMedia( '(prefers-reduced-motion: no-preference)' ). matches) { const scrollableElement= document. querySelector( '#container' ); const collisionTimeline= new ScrollTimeline({ source: scrollableElement, scrollOffsets: [ CSS. px( 200 ), CSS. px( 300 )] }); const left= leftCircle. animate({ transform: 'translate(300px)' }); left. timeline= collisionTimeline; const right= leftCircle. animate({ transform: 'translate(350px)' }); right. timeline= collisionTimeline; const union= unionCircle. animate({ opacity: 1 }, { fill: "forwards" }); union. timeline= new ScrollTimeline({ source: scrollableElement, scrollOffsets: [ CSS. px( 250 ), CSS. px( 300 )] }); }
2.2. The content progress bar
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.
The left figure shows the initial state before scrolling.
The right figure shows the progress bar is half-filled in since the user has scrolled half way through the 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:
@media ( prefers-reduced-motion: no-preference) { @scroll-timeline progress-timeline{ source : selector ( #body); scroll-offsets : 0 , 100 % ; } @keyframes progress{ to{ width : 100 % ; } } #progress{ width : 0 px ; height : 30 px ; background : red; animation : 1 s linear forwards progress progress-timeline; } }
If we use this API for this case, the example code will be as follow:
if ( window. matchMedia( '(prefers-reduced-motion: no-preference)' ). matches) { var animation= div. animate({ width: '100%' }, { fill: "forwards" }); animation. timeline= new ScrollTimeline( { scrollOffsets: [ 0 , CSS. percent( 100 )] } ); }
2.3. Combination scroll and time-base animations
2.3.1. Photo viewer
We are currently reworking this use case
3. Scroll-driven animations
3.1. Scroll timelines
3.1.1. The ScrollDirection
enumeration
enum {
ScrollDirection "block" ,"inline" ,"horizontal" ,"vertical" };
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.
3.1.2. The ScrollTimeline
interface
enum {
ScrollTimelineAutoKeyword };
"auto" typedef (CSSNumericValue or CSSKeywordish );
ContainerBasedOffset typedef (ContainerBasedOffset or ElementBasedOffset );
ScrollTimelineOffset dictionary {
ScrollTimelineOptions Element ?;
source ScrollDirection = "block";
orientation sequence <ScrollTimelineOffset >= []; }; [
scrollOffsets Exposed =Window ]interface :
ScrollTimeline AnimationTimeline {constructor (optional ScrollTimelineOptions = {});
options readonly attribute Element ?source ;readonly attribute ScrollDirection orientation ;readonly attribute FrozenArray <ScrollTimelineOffset >scrollOffsets ; };
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 duration
of a scroll timeline is 100%.
ScrollTimeline(options)
-
Creates a new
ScrollTimeline
object using the following procedure:-
Let timeline be a new
ScrollTimeline
object. -
Let source be the result corresponding to the first matching condition from the following:
- If the
source
member of options is missing, -
The
scrollingElement
of theDocument
associated with theWindow
that is the current global object. - Otherwise,
-
The
source
member of options.
- If the
-
Set the
source
of timeline to source. -
Assign the
orientation
andscrollOffsets
properties of timeline to the corresponding value from options.
-
source
, of type Element, readonly, nullable-
The scrollable element whose scrolling triggers the activation and drives the progress of the timeline.
orientation
, of type ScrollDirection, readonly-
Determines the direction of scrolling which triggers the activation and drives the progress of the timeline.
scrollOffsets
, of type FrozenArray<ScrollTimelineOffset>, readonly-
Scroll timeline offsets which determine the effective scroll offsets in the direction specified by
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
scrollOffsets
and size as thescrollOffsets
array size has the following steps:-
If val is a
DOMString
, let val be the result of rectifying the keywordish value. -
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 grammarauto
and pos equals to 0 or size - 1: -
Return val.
- If val is a
CSSNumericValue
and matches the grammar <length-percentage>: -
Return val.
- If val is an
ElementBasedOffset
: -
Return val.
- Otherwise,
-
Do not set the value and throw a
DOMException
with error nameSyntaxError
.
- If val is a
-
3.1.3. Scroll Timeline Offset
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 source
and in the direction specified by 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.
3.1.3.1. Container-based Offset
A container-based offset is a scroll timeline offset that is declared
only in relation with the scroll container as specified by source
.
A container-based offset is provided in the CSSNumericValue
or CSSKeywordValue
forms.
-
If any of the following are true:
-
source
is null, or -
source
does not currently have a CSS layout box, or -
source
's layout box is not a scroll container.
The effective scroll offset is null and abort remaining steps.
-
-
The effective scroll offset is the scroll offset corresponding to the first matching condition from the following:
- If offset is a
CSSKeywordValue
and matchesauto
: -
The beginning of
source
's scroll range inorientation
if is first is true or the ending ofsource
's scroll range inorientation
otherwise. - If offset is a
CSSNumericValue
and matches <length-percentage>: -
The distance indicated by the value along
source
's scroll range inorientation
as expressed by absolute length, a percentage, or a calc() expression that resolves to a <length>. - Otherwise,
-
null.
- If offset is a
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%'.
3.1.3.2. Element-based Offset
An element-based offset is a scroll timeline offset that is declared
in terms of the intersection of the scroll container as specified by source
and one of its descendants as specified by target
.
An element-based offset is provided in the ElementBasedOffset
form.
enum {
Edge ,
"start" };
"end" dictionary {
ElementBasedOffset Element target ;Edge edge = "start";double threshold = 0.0; };
target
, of type Element-
The target whose intersection with
source
's scrolling box determines the concrete scroll offset. edge
, of type Edge, defaulting to"start"
-
The edge of
source
's scrolling box in the direction specified by theorientation
which the target should intersect with. threshold
, of type double, defaulting to0.0
-
A double in the range of [0.0, 1.0] that represent the percentage of the target that is expected to be visible in
source
's scrollport at the intersection offset.
threshold
member is not currently
checked anywhere.
-
If any of the following are true:
-
source
is null, or -
source
does not currently have a CSS layout box, or -
source
's layout box is not a scroll container.
The effective scroll offset is null and abort remaining steps.
-
-
Let target be offset’s
target
. -
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.
-
-
If target 's nearest scroll container ancestor is not
source
abort remaining steps since the effective scroll offset is null. -
Let container box be the
source
's scrollport. -
Let target box be the result of finding the rectangular bounding box (axis-aligned in
source
’s coordinate space) of target’s transformed border box. -
If offset’s
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 byorientation
. -
If offset’s
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 byorientation
. -
Let threshold amount be the result of evaluating the following expression where target dimension is target box’s dimension in the axis determined by
orientation
.threshold amount =
threshold
× target dimension -
Adjust scroll offset by threshold amount as follow:
-
Clamp the value of scroll offset to be within the
source
's scroll range. -
The effective scroll offset is scroll offset
The left figure shows the scroller and target being aligned at "end" edge.
The right figure shows them being aligned at "start" edge.
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} ); }
The same logic can be done in CSS markup:
@media ( prefers-reduced-motion: no-preference) { @keyframes slide-in{ from{ transform : translateX ( 0 ); opacity : 0 ; } to{ transform : translateX ( 50 vw ); 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; } }
3.1.4. The effective scroll offsets of a ScrollTimeline
scrollOffsets
as follows:
-
Let effective scroll offsets be an empty list of effective scroll offsets.
-
Let first offset be true.
-
If
scrollOffsets
is empty-
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.
-
Set first offset to false.
-
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.
-
-
If
scrollOffsets
has exactly one element-
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.
-
Set first offset to false.
-
-
For each scroll offset in the list of
scrollOffsets
, perform the following steps:-
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.
-
If effective offset is null, the effective scroll offsets is empty and abort the remaining steps.
-
Add effective offset into effective scroll offsets.
-
Set first offset to false.
-
-
Return effective scroll offsets.
3.1.5. The progress of a ScrollTimeline
-
Let scroll offsets be the result of applying the procedure to resolve scroll timeline offsets for
scrollOffsets
. -
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 offset
-
Let start offset be the offset value at position offset index in scroll offsets.
-
Let end offset be the value of next offset in scroll offsets after start offset.
-
Let size be the number of offsets in scroll offsets.
-
Let offset weight be the result of evaluating
1 / (size - 1)
. -
Let interval progress be the result of evaluating
(offset - start offset) / (end offset - start offset)
. -
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 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.
3.1.6. The phase of a ScrollTimeline
The timeline phase of a ScrollTimeline
is calculated as follows:
-
If any of the following are true:
-
source
is null, or -
source
does not currently have a CSS layout box, or -
source
's layout box is not a scroll container, or -
effective scroll offsets is empty.
The timeline phase is inactive and abort remaining steps.
-
-
Let current scroll offset be the current scroll offset of
source
in the direction specified byorientation
. -
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 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
source
inorientation
: -
The timeline phase is 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 active.
3.1.7. The current time of a ScrollTimeline
The current time of a ScrollTimeline
is calculated as follows:
-
If any of the following are true:
-
source
is null, or -
source
does not currently have a CSS layout box, or -
source
's layout box is not a scroll container, or -
effective scroll offsets is empty.
The current time is an unresolved time value and abort remaining steps.
-
-
Let current scroll offset be the current scroll offset of
source
in the direction specified byorientation
. -
The current time is the result corresponding to the first matching condition from below:
- If current scroll offset is less than effective start offset:
-
The current time is 0.
- If current scroll offset is greater than or equal to effective end offset:
-
The current time is the
duration
. - Otherwise,
-
-
Let progress be a result of applying calculate scroll timeline progress procedure for current scroll offset.
-
The current time is
progress ×
duration
-
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 target
is not a descendant of the scroll timeline source
, the timeline remains inactive.
3.2. The @scroll-timeline at-rule
Scroll timelines are specified in CSS using the @scroll-timeline at-rule, defined as follows:
<@scroll-timeline> = @scroll-timeline <timeline-name> { <declaration-list> }
An @scroll-timeline rule has a name given by the <custom-ident> or <string> in its prelude. The two syntaxes are equivalent in functionality; the name is the value of the ident or string. As normal for <custom-ident>s and <string>s, the names are fully case-sensitive; two names are equal only if they are codepoint-by-codepoint equal. The <custom-ident> additionally excludes the none keyword.
Once specified, a scroll timeline may be associated with a CSS Animation [CSS3-ANIMATIONS] by using the animation-timeline property.
The <declaration-list> 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.
This will likely change in the future. [Issue #5167]
3.2.1. Scroll Timeline descriptors
Name: | source |
---|---|
For: | @scroll-timeline |
Value: | selector( <id-selector> ) | auto | none |
Initial: | auto |
source descriptor determines the scroll timeline’s source
,
with the following values:
- selector()
-
The scroll container identified by the <id-selector>.
- auto
-
The
scrollingElement
of theDocument
associated with theWindow
that is the current global object. - none
-
null.
Consider choosing animation target’s nearest scrollable ancestor
instead of document’s scrolling Element for auto
. [Issue #4338]
Name: | orientation |
---|---|
For: | @scroll-timeline |
Value: | auto | block | inline | horizontal | vertical |
Initial: | auto |
orientation descriptor determines the scroll timeline’s orientation
.
Name: | scroll-offsets |
---|---|
For: | @scroll-timeline |
Value: | none | <scroll-timeline-offset># |
Initial: | none |
scroll-offsets descriptor determines the scroll timeline’s scrollOffsets
.
Scroll timeline offsets in CSS are represented by the <scroll-timeline-offset> type:
<scroll-timeline-offset> = auto | <length-percentage> | <element-offset> <element-offset> = selector( <id-selector> ) [<element-offset-edge> || <number>]? <element-offset-edge> = start | end
The offset type depends on the value of <scroll-timeline-offset> per following:
- If value is "auto" or of type <length-percentage>
-
The scroll timeline offset is a container-based offset with the same value.
- If value is of type <element-offset>
-
The scroll timeline offset is an element-based offset with the following member values:
-
target
is the element identified by <id-selector>. -
edge
is the optional value of <element-offset-edge>. If not provided it defaults to "start". -
threshold
is the optional value <number>. If not provided it defaults to 0.
-
3.2.2. The CSSScrollTimelineRule
Interface
[Exposed =Window ]interface CSSScrollTimelineRule :CSSRule {readonly attribute CSSOMString name ;readonly attribute CSSOMString source ;readonly attribute CSSOMString orientation ;readonly attribute CSSOMString scrollOffsets ; };
name
, of type CSSOMString, readonly- The name associated with the @scroll-timeline rule.
source
, of type CSSOMString, readonly- The source descriptor associated with the @scroll-timeline, or "auto" if not specified.
orientation
, of type CSSOMString, readonly- The orientation descriptor associated with the @scroll-timeline, or "auto" if not specified.
scrollOffsets
, of type CSSOMString, readonly- The scroll-offsets descriptor associated with the @scroll-timeline, or "none" if not specified.
-
The string
"@scroll-timeline"
followed by a SPACE (U+0020). -
The result of performing serialize an identifier on the rule’s
name
, followed by a SPACE (U+0020). -
A single LEFT CURLY BRACKET (U+007B), followed by a SPACE (U+0020).
-
If the source descriptor is missing, the empty string. Otherwise, the concatenation of the following:
-
The string
"source:"
, followed by a SPACE (U+0020). -
One of the following, depending on the value of the source descriptor:
- an identifier
-
The result of performing serialize an identifier on that identifier.
- selector(<id-selector>)
-
The result of performing serialize a selector() function.
-
A single SEMICOLON (U+003B), followed by a SPACE (U+0020).
-
-
If the orientation descriptor is missing, the empty string. Otherwise, the concatenation of the following:
-
The string
"orientation:"
, followed by a SPACE (U+0020). -
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).
-
-
If the scroll-offsets descriptor is missing, the empty string. Otherwise, the concatenation of the following:
-
The string
"scrollOffsets:"
, followed by a SPACE (U+0020), followed by a LEFT SQUARE BRACKET (U+005B). -
For each value in the list for the rule’s scroll-offsets descriptor:
-
The result of performing serialize a scroll timeline offset on the value.
-
If not the last value, A COMMA (U+002C), followed by a SPACE (U+0020).
-
-
A RIGHT SQUARE BRACKET (U+005D), followed by a SEMICOLON (U+003B), followed by a SPACE (U+0020).
-
-
A single RIGHT CURLY BRACKET (U+007D).
- an identifier
- <length-percentage>
-
The result of performing serialize a CSS component value on that value.
- <element-offset>
-
The concatenation of the following:
-
The result of performing serialize a selector() function on the selector() function associated with the element offset.
-
If the offset has an associated
edge
, a single SPACE (U+0020), followed by the result of serialize an identifier on the value of "edge". Otherwise, the empty string. -
If the offset has an associated
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.
-
-
The string
"selector"
, followed by LEFT PARENTHESIS (U+0028). -
The result of performing serialize a selector on the selector() function’s argument.
-
A single RIGHT PARENTHESIS (U+0029).
3.3. Examples
#progress{ position : fixed; top : 0 ; width : 0 ; height : 2 px ; background-color : red; }
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(); }
@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 : 0 vw ; } to{ width : 100 vw ; } } #progress{ position : fixed; top : 0 ; width : 0 ; height : 2 px ; 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; } }
4. Avoiding cycles with layout
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
This appendix is informative.
There are no known security or privacy impacts of this feature.
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.
-
Does this specification deal with high-value data?
No.
-
Does this specification introduce new state for an origin that persists across browsing sessions?
No.
-
Does this specification expose persistent, cross-origin state to the web?
No.
-
Does this specification expose any other data to an origin that it doesn’t currently have access to?
No.
-
Does this specification enable new script execution/loading mechanisms?
No.
-
Does this specification allow an origin access to a user’s location?
No.
-
Does this specification allow an origin access to sensors on a user’s device?
No.
-
Does this specification allow an origin access to aspects of a user’s local computing environment?
No.
-
Does this specification allow an origin access to other devices?
No.
-
Does this specification allow an origin some measure of control over a user agent’s native UI?
No.
-
Does this specification expose temporary identifiers to the web?
No.
-
Does this specification distinguish between behavior in first-party and third-party contexts?
No.
-
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.
-
Does this specification persist data to a user’s local device?
No.
-
Does this specification have a "Security Considerations" and "Privacy Considerations" section?
Yes.
-
Does this specification allow downgrading default security characteristics?
No.