You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: css-view-transitions-2/two-phase-transition-explainer.md
+27-48Lines changed: 27 additions & 48 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,11 +7,13 @@ See whatwg/html#10616, whatwg/html#11819 and w3c/csswg-drafts#12829.
7
7
The period between initiating a navigation (e.g. clicking a link) and consuming the content of the next page ([FCP](https://web.dev/articles/fcp)), is a sensitive moment in user experince.
8
8
It is a point in time where users are very likely to notice delays, jarring moments of frozen display, and abrupt changes to presentation.
9
9
10
-
The core of this being difficult stems from a tradeoff between speed and smoothness.
11
-
The new document becomes activate ASAP (in favor of speed), at the moment the headers are received.
12
-
However, it cannot render until all of its render-blocking resources and elements are present (in favor of smoothness, preventing FoUCs).
10
+
The core of this being difficult stems from a tradeoff between speed and smoothness:
11
+
-The new document becomes activate ASAP (in favor of speed), at the moment the headers are received.
12
+
-However, it cannot render until all of its render-blocking resources and elements are present (in favor of smoothness, preventing FoUCs).
13
13
14
-
This "uncanny valley" where the old page is no longer active but the new page cannot render anything is far from being an optimal user experience, and the knobs given for developers to control it are crude and implicit.
14
+
So, in the cases where the navigation is not instant, providing some instant animated response might cause an experience that doesn't feel smooth.
15
+
16
+
This "uncanny valley" where the old page is no longer active but the new page is not rendering any frames is far from being an optimal user experience, and the knobs given for developers to control it are crude and implicit.
15
17
16
18
# Current knobs
17
19
@@ -28,65 +30,42 @@ This would feel smoother but slows down the whole navigation and tweaking it cor
28
30
## Timing out render-blocking
29
31
This can reduce the jarring time, however it means the transition doesn’t end at the optimal state, and also doesn’t help with making it feel instant.
30
32
31
-
# Two-phase transition
33
+
# Proposed solutions
32
34
33
35
To make this part of the experience feel more seamless, developers should be able to create a "two-phase page transition".
34
36
This transition starts *instantly* after navigation initiation (link click), and continues *smoothly* until the next page is ready to render.
35
37
The instant part of the transition can only use information knows to the old page, which could be a skeleton of the new page or something generic of sorts.
36
38
37
-
To achieve that, there are 3(?) potential avenues
39
+
To achieve that, proposing two provide the following:
38
40
39
-
## Heuristic-based
40
-
Allow a subset of animations, e.g. ones that started after the navigation was initiated, to continue until the new page is ready to commit.
41
-
This would allow instant reactions to a navigation while not creating the abrupt experience of spotting it prematurely.
41
+
## Allowing the author to control the commit scheduling
42
42
43
-
## Low-level knobs with prerendering support
44
-
Currently, deferring the commit, even for same-origin navigation, is not possible. So the browser is responsible for the handover,
45
-
not allowing the developer to curate this experience.
43
+
```js
44
+
// Returns a boolean if the page is prerendered/BFCached and not render-blocked.
45
+
navigateEvent.nextDocumentReadyToRender
46
46
47
-
### Deferring commit
48
-
Something like `navigateEvent.waitUntil(promise)` (or `defer` or some such) can let the developer tweak the handover point.
49
-
This can of course also be a footgun as it's a simple way to delay navigations, however it's arguably less of a footgun than the current workarounds.
47
+
// Allows delaying the commit *without* intercepting as a same-document navigation.
48
+
navigateEvent.deferCommit(promise)
49
+
```
50
50
51
-
### Responding to prerender
52
-
When prerendering takes place, a more sensible time to hand over the control to the new document is when it is ready to produce a frame (all the render-blocking resources had been discovered).
53
-
However, it is not guaranteed that the destination page is prerendered, and there is no hook to know when the new page is ready to render.
A rather low level way to expose this is `navigateEvent.prerender()` which initiates a prerender if that hasn't happened yet, and returns a promise that resolves at that point, and compose it with the `waitUntil` method above.
56
-
It is also possible to short-circuit this and somehow declare "please defer commit until prerender", which is perhaps safer than a general-purpose promise-based API.
57
59
58
-
## Declarative preview transitions
60
+
## Allowing animations to defer commit for a short period
59
61
60
-
The above knobs might be very effective, but might also require expertise to get right.
62
+
The above knobs can be very effective, but might also require expertise to get right.
61
63
62
-
```css
63
-
@view-transition {
64
-
navigation: preview;
65
-
types: skeleton;
66
-
}
67
-
68
-
:active-view-transition-types(skeleton) {
69
-
/* style the transition here */
70
-
}
71
-
```
72
-
73
-
This is especially expressive together with route-matching:
64
+
The likely use case to let an animation continue till the end, so we can perhaps enable this declaratively:
74
65
75
66
```css
76
-
@route (from: movie-list) and (to: movie-details) {
77
-
@view-transition {
78
-
navigation: preview;
79
-
types: skeleton;
80
-
}
81
-
}
82
-
83
-
@route (movie-details) {
84
-
:active-view-transition-types(skeleton) {
85
-
/* style the page as a details page skeleton even if we don't have all the data */
86
-
}
67
+
::view-transition-group {
68
+
animation-navigation-behavior: smooth;
87
69
}
88
70
```
89
71
90
-
# Conclusion
91
-
Proposing to pursue both the declarative and JS-based approach for completeness (one for ease of use, one for fine-tuning and complete control), and avoid the heuristic approach as it'sa bit opaque and implicit.
0 commit comments