Skip to content

Commit 0cd9482

Browse files
authored
Create two-phase-transition-explainer.md (#12819)
1 parent c2c2f2e commit 0cd9482

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Two-phase view transition
2+
Making cross-document view-transitions feel instant and seamless.
3+
4+
See w3c/csswg-drafts#10616
5+
6+
# Current state
7+
View-transitions don’t start immediately - rendering is paused until the new state is ready.
8+
This is especially visible in cross-document view transitions, where the transition only captures the old when the new document’s response arrives, and starts when the new document is ready to render.
9+
10+
This can create a jarring or abrupt experience.
11+
12+
# Current workarounds
13+
14+
## Starting an animation manually on the old page
15+
This is possible, however the old page cannot delay the navigation, which means the animation is likely to be interrupted when the navigation commits.
16+
17+
## Intercepting the navigation and restarting it when the animation ends
18+
This works but is hard to achieve without slowing down the whole navigation process.
19+
20+
## Timing out render-blocking
21+
This can reduce the “frozen” time, however it means the transition doesn’t end at the optimal state, and also doesn’t help with making it feel instant.
22+
23+
# Proposed solution
24+
The core of the problem is that view-transitions require a start and an end phase before starting, but we don’t know the end phase in advance when it is computed in an async function (e.g. in a navigation).
25+
26+
## In a nutshell
27+
Proposing to prototype a “two-phase” view-transition:
28+
Instantly start a transition to a state that can be computed quickly enough or synchronously. Call this a “preview” state.
29+
When the to-preview transition ends, transition from there to the final state.
30+
Only interrupt the first transition after a timeout, otherwise stall the navigation commit until finished.
31+
This should ideally not delay the LCP / loading experience of the new page, as the content keeps loading (and potentially prerendering) in the background.
32+
33+
## Phase 1: script-invoked preview
34+
We can create this kind of seamless/instant experience without any new CSS, and potentially without needing to fully spec it normatively by changing the behavior as follows:
35+
Calling document.startViewTransition while there is an uncommitted navigation currently works, however it might get cancelled if the navigation is committed.
36+
Instead, if setting up that preview transition’s new state is fast enough so that it is activated before commit, let the animation run its course and use the final state as the “old” state for the cross-document view-transition.
37+
38+
## Phase 2: declarative, using route-matching
39+
Instead of relying on carefully crafted scripts, use the proposed [declarative routing feature](https://github.com/WICG/declarative-partial-updates/blob/main/route-matching-explainer.md), and compute the preview value declaratively and synchronously by applying the style associated with the new route and using it as the intermediate state.
40+
41+
Something like this, though perhaps the “preview” opt-in is not necessary and we can make this inferred
42+
43+
@route (to: article) {
44+
.article-skeleton { display: block }
45+
}
46+
47+
@view-transition {
48+
navigation: preview;
49+
}
50+
51+
The big advantage of doing this declaratively is that the author doesn't have to worry about "cleaning up after themselves", e.g. in the case of restoring from BFCache.
52+
Since routing is declarative, the style of the "new" route would simply not apply when restoring the "old" page from BFCache because the user is no longer navigating to it.
53+
54+

0 commit comments

Comments
 (0)