Skip to content

Commit d919543

Browse files
committed
[scroll-animations-1] Polish explainer
1 parent 6708875 commit d919543

File tree

1 file changed

+44
-41
lines changed

1 file changed

+44
-41
lines changed

scroll-animations-1/EXPLAINER.md

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Currently the only way to achieve them is to respond to scroll events on the mai
3434
means that these animations have to run on the main thread which leads to two main problems:
3535
1. Modern browsers perform scrolling on separate thread/process so scroll events are delivered
3636
asynchronously.
37-
2. Main thread animations are subject to jank.
37+
2. Main thread animations are subject to jank.
3838

3939
These make creating performant scroll-linked animations that are in-sync with
4040
scrolling impossible or [very
@@ -59,7 +59,7 @@ position and and not their progress.
5959
However, we found that in the vast majority of cases where a web author would want to do this, they
6060
would want to do it for a CSS transition (as opposed to a CSS animation). Unfortunately, it's not
6161
possible to trigger CSS transitions from the compositor thread (because triggering a transition
62-
requires style resolution, which cannot be performed on the compositor thread).
62+
requires style resolution, which cannot be performed on the compositor thread).
6363

6464
Earlier versions of this specification included a triggering mechanims. But given the extent to
6565
which triggering complicated the API and because of the smaller benefit that these type of
@@ -181,7 +181,7 @@ div.circle {
181181
}
182182
#right-circle {
183183
animation-name: right-circle;
184-
animation-timeline: collision-timeline;
184+
animation-timeline: collision-timeline;
185185
}
186186
#union-circle {
187187
animation-name: union-circle;
@@ -235,8 +235,8 @@ const scroller = document.getElementById("scroller");
235235
const image = document.getElementById("image");
236236

237237
const revealTimeline = new ScrollTimeline({
238-
// Timeline starts at the offset that corresponds with image starting
239-
// to enter scrollport (i.e., 0% intersect with scroller at itsendedge).
238+
// Timeline starts at the offset that corresponds with image starting
239+
// to enter scrollport (i.e., 0% intersect with scroller at itsendedge).
240240
start: { target: image, edge: 'end', threshold: 0 },
241241

242242
// Timeline ends at the offset that corresponds with image becoming
@@ -249,7 +249,7 @@ const animation = new Animation(
249249
image,
250250
{ opacity: [0, 1]},
251251
{ duration: 1000, fill: both }
252-
),
252+
),
253253
revealTimeline
254254
);
255255

@@ -283,21 +283,21 @@ document.querySelector('.header > .background').animate({
283283
});
284284
}
285285
```
286-
286+
287287
### Scenario 2 - Reveal/Unreveal
288288

289289
In this UX pattern an element fades in/out or swipes in/out as user scrolls the page. These are
290290
often used to create interactive stories. For example see how New York Times applies scroll-linked
291291
animations for creative
292292
[storytelling](http://www.nytimes.com/projects/2013/tomato-can-blues/index.html).
293-
293+
294294
![Reveal example](https://gist.github.com/majido/a1279d6d986ab8881d51a77e98769e69/raw/explainer-reveal.gif)
295295

296296

297297
Here is a simple example where we reveal each header as they enters the viewport. This example uses
298298
the still unspecified element-based offset syntax.
299299

300-
300+
301301
```js
302302
const headers = document.querySelectorAll('h2, h3');
303303
for (let i = 0; i < headers.length; i++) {
@@ -308,15 +308,15 @@ the still unspecified element-based offset syntax.
308308

309309
headers[i].animate([
310310
{transform: 'translateX(-10px)', opacity: 0},
311-
{transform: 'none', opacity: 1}],
311+
{transform: 'none', opacity: 1}],
312312
{
313313
duration: 10000,
314314
fill: 'both',
315315
timeline: scrollTimeline
316316
}
317317
);
318318
}
319-
}
319+
}
320320
```
321321

322322
### Scenario 3 - Progress-bar Animation
@@ -326,7 +326,7 @@ to indicate the reader’s position in a long article.
326326

327327
![Progressbar example](https://gist.github.com/majido/a1279d6d986ab8881d51a77e98769e69/raw/explainer-progressbar.gif)
328328

329-
Below is a simple example where a progress bar is animate from 0 to full width as we scroll the
329+
Below is a simple example where a progress bar is animate from 0 to full width as we scroll the
330330
document.
331331

332332
``` js
@@ -338,13 +338,13 @@ document.querySelector('#progressbar').animate({
338338
source: document.scrollingElement
339339
})
340340
});
341-
```
342-
341+
```
342+
343343
### Image Zoom In/Out
344344
345345
This is another common usage pattern when an image scales up to fill a larger canvas. For an
346-
example of this see [iPhone 11 launch site](https://www.apple.com/iphone-11/).
347-
346+
example of this see [iPhone 11 launch site](https://www.apple.com/iphone-11/).
347+
348348
![Zoom example](https://gist.github.com/majido/a1279d6d986ab8881d51a77e98769e69/raw/explainer-zoom.gif)
349349
350350
In this example we start scaling a DIV as soon as its container fully enters the scrollport and
@@ -371,9 +371,9 @@ document.querySelector('#zoom > div').animate({
371371
372372
Using Web Animations API was a key decision. On the upside it has many benefits: using established
373373
concepts and models for animation/keyframe/easing etc. This means scroll animations can be created,
374-
controlled, and inspected with existing methods.
374+
controlled, and inspected with existing methods.
375375
376-
Some of the complexities that come from this decision are:
376+
Some of the complexities that come from this decision are:
377377
378378
* **Time vs Scroll Offset**: The concept of **time value** (exposed in
379379
Milliseconds units) are central to the Web Animation model. This is why
@@ -383,7 +383,7 @@ Some of the complexities that come from this decision are:
383383
[1](https://github.com/w3c/csswg-drafts/issues/4346) and
384384
[2](https://github.com/w3c/csswg-drafts/issues/4353)). A more principled
385385
solution has been proposed in the form of Progress-based Animations which
386-
addresses this issue among other benefits.
386+
addresses this issue among other benefits.
387387
388388
* **Exclusive end ranges**: In Web Animations, ranges have exclusive ends to
389389
help make it easier to use overlapping ranges such as putting multiple
@@ -405,21 +405,20 @@ The ability for scrolling to drive the progress of an animation, gives rise to t
405405
layout cycles, where a change to a scroll offset causes an animation’s effect to update, which in
406406
turn causes a new change to the scroll offset. Imagine that an animation shrinks the height of the
407407
content of the scroller which may cause the max scroll offset to reduce which may change the scroll
408-
offset.
409-
408+
offset.
410409
411410
To avoid such layout cycles, animations with a ScrollTimeline are sampled once per frame, after
412411
scrolling in response to input events has taken place, but before `requestAnimationFrame()`
413412
callbacks are run. If the sampling of such an animation causes a change to a scroll offset, the
414-
animation will not be re-sampled to reflect the new offset until the next frame.
415-
413+
animation will not be re-sampled to reflect the new offset until the next frame.
414+
416415
![Ordering of scroll-linked animations](img/explainer-ordering.svg)
417416
418417
Note that this ensures the output of scroll-linked animation is always up-to-date when the user is
419418
scrolling and avoids layout cycle. But it also means that in some situations the rendered scroll
420419
offset may not be consistent with the output of scroll-driven animations. For example when the
421420
scroll-linked animation itself is indirectly causing the scroll offset to change. We believe this
422-
is rare and often not actually desired by authors.
421+
is rare and often not actually desired by authors.
423422
424423
425424
Another thing to note is that if one updates scroll offsets in a `requestAnimationFrame` callback
@@ -432,14 +431,14 @@ scroll-linked animations.
432431
Most modern browsers [perform scrolling
433432
asynchronously](https://blogs.windows.com/msedgedev/2017/03/08/scrolling-on-the-web/) to ensure
434433
smoothness and responsiveness to user actions. In other words the majority of scrolling is handled
435-
off main-thread. We have opted for the following model to ensure that is not affected:
434+
off main-thread. We have opted for the following model to ensure that is not affected:
436435
437436
1. The scroll-linked effects are expressed declaratively similar to other
438-
web-animations and may be sampled asynchronously.
437+
web-animations and may be sampled asynchronously.
439438
2. The user-agent is allowed to sample scroll-linked animations more often than main
440439
thread animation frames.
441440
3. The user-agent is allowed to sample the scroll-linked effects on main-thread once
442-
per main-thread animation frame and use the last known scroll offset.
441+
per main-thread animation frame and use the last known scroll offset.
443442
444443
445444
(1) and (2) mean that scroll-linked animation can potentially run off-main thread and in sync with
@@ -450,22 +449,22 @@ enabling user-agents to optimize such animations to potentially run off-thread a
450449
asynchronous scrolling.
451450
452451
### Progress-Based Animations
453-
452+
454453
As mentioned before we like to eliminate the need for `ScrollTimeline.timeRange` to map scroll
455454
units into time units. One approach we are exploring is the addition of progress-based animations
456455
to Web Animations. This will allow the scroll timeline to produce a “progress” value which can
457456
drive animations without a need for durations. Progress-based animations will have other value
458457
beside scroll linked-animations. This is a work-in-progress and there is an ongoing discussion
459458
around it [here](https://github.com/w3c/csswg-drafts/issues/4862).
460-
459+
461460
### Access top-level window scroll in iframes
462461
463462
It is desirable to perhaps allow scroll-linked animations to respond to the top-level window
464463
viewport in an iframe. The current specification does not allow this as we are not sure of the
465464
security impact of enabling this in cross-origin iframes. But in terms of API it may be just as
466465
simple of allowing empty source attributes to mean top-level window scroller. More discussion on
467466
the use case and possible solutions are [here](https://github.com/w3c/csswg-drafts/issues/4344)
468-
467+
469468
### Logical Scrolling vs Animation of Physical properties
470469
471470
This is not an issue directly related to Scroll-linked animation but one that gets exposed more
@@ -476,23 +475,24 @@ animate physical properties. More details on this [issue
476475
here](https://github.com/w3c/csswg-drafts/issues/4350#issue-495584798). Long-term, perhaps we
477476
should consider [logical transforms](https://github.com/w3c/fxtf-drafts/issues/311) (also
478477
[this](https://github.com/w3c/csswg-drafts/issues/1788)).
479-
478+
480479
## Considered alternatives
481480
482-
### CSS Syntax
483-
We have considered alternatives function based css syntax but decided to go with a @scroll-timeline rule
484-
instead. See additional CSSWG discussion [here](https://github.com/w3c/csswg-drafts/issues/4338).
481+
### CSS Syntax Alternatives
482+
We have considered alternatives function based css syntax but decided to go with a @scroll-timeline
483+
rule instead. See additional CSSWG discussion
484+
[here](https://github.com/w3c/csswg-drafts/issues/4338).
485485
486486
487-
### Element-based start/end Offsets
487+
### Element-based start/end Offsets Alternatives
488488
489489
A common usage pattern for scroll-linked animation is to start animation when an element enters
490490
scrollport (or viewport) until it leaves viewport. The current proposal achieves this by allowing
491491
start/end offset to be declared in terms of intersection of the scroller and one of its
492492
descendants. This is still a work-in-progress but most of the details are spelled out
493493
[here](https://github.com/w3c/csswg-drafts/issues/4337).
494494
495-
Below are alternatives we have considered:
495+
Below are alternatives we have considered:
496496
497497
1. Only expose static offsets and leave it to authors to compute these offset based on element and
498498
scroller bounding client rects. While this seems simple on surface but putting the onus on
@@ -525,8 +525,6 @@ there is no need to expose scroll offsets directly. This can enable more complex
525525
animations using Animation Worklet while also making it easy to create fully declarative animations
526526
for common simpler use cases via Web Animations.
527527
528-
#### Non-Scalar time values which could include length/scroll position
529-
530528
Another [take on this idea](https://github.com/w3c/csswg-drafts/issues/2493) was to change Web
531529
Animations time value to no longer be scalar but value could be a bag of values which may be scroll
532530
positions, touch position etc. This combined with custom js animation callback, such as Animation
@@ -535,11 +533,16 @@ believed this may not be compatible with the Web Animation model.
535533
536534
537535
## Stakeholder Feedback / Opposition
538-
Safari, Mozilla, Chrome, Edge are in favor of the idea. There are engineers from all four browsers
539-
as editors in the specification.
536+
Safari, Mozilla, Chrome, Edge are participating in CSSWG and have been supportive of the idea.
537+
There are engineers from all four browsers as editors in the specification.
538+
539+
Additional links
540+
- [Mozilla standard positions](https://github.com/mozilla/standards-positions/issues/347)
541+
- [Chromium status](https://chromestatus.com/feature/6752840701706240)
542+
- TODO: Webkit-dev thread
540543
541544
## References & acknowledgements
542-
Many thanks for valuable contributions, feedback and advice from:
545+
Many thanks for valuable contributions, feedback and advice from:
543546
* All current and former specification editors.
544547
* CSSWG members for valuable feedback on this proposal.
545548
* Yi Gu <yigu@google.com> for contributing to this explainer.

0 commit comments

Comments
 (0)