-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
View Transitions API #748
Comments
Hey folks, we just updated the explainer. It should give a better overview of the feature now https://github.com/WICG/shared-element-transitions/blob/main/explainer.md. The previous version was written before we had a spec, so included some lower-level detail which is better left to the spec. |
Hi Jake, We looked at this during the plenary today. We generally recognize the importance of solving these very common use cases and understand that to cover enough of them, the solution would need a certain degree of complexity. However, we did have some trouble wrapping our heads around exactly how this works and how the different pieces fit together. While it is very clear that a lot of effort has been put into this explainer, we also feel that some parts assume certain knowledge about the reader. We would like to see more examples of both code and output, as well as some simpler examples that may not look nice, but illustrate how the API works. A few hello worlds of sorts 😊 Or perhaps it may help to pick two of these examples and provide the end to end code for them somewhere? |
Does the developer guide provide that kind of introduction? https://developer.chrome.com/blog/shared-element-transitions-for-spas/ - each of the demos has a video, but also a link to a super simple example. There's also a 10 min video on the feature if that works better https://www.youtube.com/watch?v=JCJUPJ_zDQ4. The difference between the developer document and the explainer, is the explainer uses the latest API (which hasn't landed in Chrome yet), and contains a few more implementation details. |
Yes! At least for me this was a lot clearer. Is there anything similar about MPAs? |
What are the next steps here? I could merge the more-gradual-introduction from https://developer.chrome.com/blog/shared-element-transitions-for-spas/ into the explainer. |
The next step is that we revisit this in another call. I see it now has a milestone of 2022-08-22-week, which means the intent is to revisit it next week. I wonder if part of the reason it was so hard to wrap our heads around this was that the explainer was already very long, so it was hard to know what to focus on when reviewing it during the call. This is a complex feature, so it does need a lot of, well, explaining, but I wonder if it might be easier to digest if organized hierarchically, breadth-first. Also, despite the length, we felt there were certain pieces of the puzzle missing, e.g.:
const transition = new SameDocumentTransition();
await transition.prepare(async () => {
await updateTheDOMSomehow();
}); that is just repeated throughout the explainer. It took until the link you posted above for me to finally understand how this works: You start the transition by creating a
Hope this helps a bit! While writing this, I had some thoughts about the actual API: It would be nice if there was a way to use SET without the extensive refactoring of having to put the DOM manipulation code in the I also just noticed that this doesn't support MPAs yet, but that's an API sketch. Since that's a pretty central use case, I'll make sure we spend call time reviewing that sketch too, and not just the SPA part of the API. |
This is great feedback. What day & time are folks likely to look at this? As in, assuming I'm not working the weekend (which I plan not to), how long do I have to bash the explainer into shape?
The browser needs to capture the 'before' state, which is async. But yeah: const transition = new SameDocumentTransition();
await transition.prepare(async () => {
await updateTheDOMSomehow();
}); …could have an alternative API like: const transition = new SameDocumentTransition();
await transition.captureBeforeState();
await updateTheDOMSomehow();
transition.domChanged(); The main difference between the two is if With the callback model, it's more likely that we catch the error, and know to abandon the transition. WebLocks use a similar pattern for this reason.
Depends on the framework. I created a React hook to do it, and it's what https://http203-playlist.netlify.app/ uses. React has |
Our current schedule is to look at this again on 8/22 @18:00CET, but we can easily defer a week or two if you need more time. |
I'm up for the challenge. I'll confirm here when I've updated the explainer. |
Done! https://github.com/WICG/shared-element-transitions/blob/main/explainer.md Hopefully the explainer now starts off at a high level, then goes on to explore some of the details. For additional details, the spec may be useful https://tabatkins.github.io/specs/css-shared-element-transitions/. If it still isn't good, and you need to bail on it, there's always #761 to review instead 😄 |
Thank you for working on the explainer, the new one is vastly improved and much easier to follow! 👍🏼
I understand, but the callback model makes this very annoying to use w/ progressive enhancement, and the Web Platform in general is trying to move away from callback-based APIs. This is exactly the kind of API that would benefit from progressive enhancement, since if it's not available, you just don't get a transition, no big deal. It should be easy to write code that works this way. And lack of this feature is not the only reason people might want to branch and only have the transitions some of the time. E.g. the if (animationsEnabled && globalThis.SameDocumentTransition) {
const transition = new SameDocumentTransition();
await transition.prepare(async () => {
await updateTheDOMSomehow();
});
}
else {
await updateTheDOMSomehow();
} whereas with your alternative API sketch: const transition = animationsEnabled && globalThis.SameDocumentTransition ? new SameDocumentTransition() : null;
await transition?.captureBeforeState();
await updateTheDOMSomehow();
transition?.domChanged(); Having the rendering be frozen until a timeout could not be such a dealbreaker if the timeout is explicitly specified when creating the transition? After all, DOM manipulation is not a lengthy process (compared to e.g. network requests), so you'd likely need a very small timeout, smaller than the threshold of a lag that is perceptible by humans (60ms). You could also take a signal to abort the operation, which is good practice anyway. Note that the current API can still cause rendering to freeze, if you await a promise that never resolves.
I’m sure it's possible with every framework, but it's yet another obstacle for authors to figure out which advanced framework feature would do this. E.g. off the top of my head I cannot think of how to reliably do this with Vue, at least not without heuristics and hacks. |
We looked at this again today and had some questions:
We are particularly concerned about the complexity and ergonomics of this API, and we (TAG members) have not yet had the a-ha moment where we fully understand how all the pieces come together to create a transition in a real use case from scratch. Given the trouble we've had with it, that gives us some pause about DX in the wild. Perhaps it's an inherently complicated problem and there cannot possibly be a simpler solution, but it is a concern that came up several times in our discussions. Regarding #748 (comment) , with the current API, Re:frameworks, I’m sure it's possible, and yes it doesn't look too bad, but it's unfortunate that it requires people to find out implementation details like |
Yes. Canary is up to date, the last syntax changes landed in 109.0.5410.0.
Feedback from authors has been quite positive since the pseudo-DOM structure can be animated using existing APIs and debugged via existing devtools support. A few interesting patterns which have come up from experimentation are:
We had a breakout session describing how the feature works at BlinkOn today. I'll post a link of the recording which would hopefully help with understanding the full design. Will let @jakearchibald comment on the ergonomics of the callback based API. |
I don't think this will be a huge issue in practice, as I expect developers will write a little helper function like this: async function doViewTransition(callback) {
const skipTransition =
!document.startViewTransition ||
matchMedia('(prefers-reduced-motion)').matches ||
localAppConfig.skipTransitions;
if (skipTransition) {
callback();
return null;
}
await document.startViewTransition(callback).domUpdated;
} Then the usage would be: await doViewTransition(() => {
header.classList.add('whatever');
}); Even in a world where all browsers support view transitions, a helper is handy for centralising skipping transitions for reasons that are specific to the site (like reduced motion and
I don't think there's a model we can adopt where you wouldn't need to know about My hope is that each framework will have a hook/component that wraps this, and turns state changes into transitions, similar to what they already do with animations, but with much less code. If you haven't had an a-ha moment with this, then my docs suck. That's probably because I'm too deep in the spec/implementation. Would you be up for a video call where we talk through the API & examples? Hopefully the a-ha moment will happen, and you can tell me what details should have been at the very top of the docs, in bold, rather than buried somewhere 😄 |
And here is a recording of the session at BlinkOn. It's focused on Blink/Chromium specific implementation details for some parts but covers the general web platform concepts too. |
@jakearchibald and I had a call about this yesterday, and I think I now understand how this works and how the different pieces come together a lot better. We later discussed this again with other TAG members in a breakout. We are aware that you have all been thinking about this for a lot longer than we have, and it's entirely possible that you've already explored all this and concluded the current API shape is a necessary compromise, but in case it helps, these were our thoughts:
We wondered if it could prevent some of these issues and allow more room for future expansion if In general, we'd like to see a layered, gradual approach, where a small amount of declarative CSS syntax can address common use cases, more CSS can customize the transitions further, and JS is needed to customize behavior even further than that. This is also in line with how existing CSS transitions and animations work, where syntax is gradually added to customize further, but very little syntax is needed to produce an initial result. We also think tighter collaboration between the designers of this API and the CSS WG could help address some of these issues. |
Completely agreed with the goal to keep the syntax as declarative as possible. I’ll clarify the challenge with being able to do the work of the JS API with a declarative syntax, and would love to hear TAG’s ideas for it. The JS API is needed because the UA needs an explicit signal to render and cache the old DOM state before the DOM is changed. This signal doesn't need to be JS-driven, as proven by the MPA version of the API which uses cross-document navigations as the signal. The only difference between the MPA and SPA versions of the API is this signal, the rest is the same. In SPAs, JS is already driving the DOM change, so it seems reasonable for JS to be used to signal these states. It wouldn't be impossible to do this all in CSS (in theory we can add as much syntax as we want), but I'm not confident it would be easier for developers to use. A good example for a DOM change triggered declaratively would be the :hover pseudo-class. A strawman proposal for a completely declarative view transition in this case would require:
Admittedly I don't know how this could be done in JS, and it attests to your point that there are cases where declarative syntax would be needed. However, that doesn't mean we couldn't add additional ways to provide this signal going forward for such cases. The design of view-transitions allows for this kind of thing to be explored.
+1 for declarative transitions on hash navigations, this has come up before. Filed #8300 to discuss this in CSSWG.
I’m assuming you mean transitions for changes in a third party component which doesn’t provide the requisite signals required by
Agreed. #8048 is tracking that.
There are going to be declarative hooks for the common customization cases in CSS. For instance, based on the old/new Document URL; or by pages assigning themselves a tag/name/class/category which can be used in CSS. It might be more ergonomic to express the customization based on going from “index” to “article" rather than going from The JS component of the cross-document API could also allow passing opaque contextual data between pages for this customization but this warrants more discussion, filed #8303 for this. Note that the API surface specific to cross-document/navigation triggered transitions is in very early stages right now. There is a prototype but the MPA API is being iterated on as level 2 of this spec, you can see CSSWG issues here. We'd like TAG to scope this review to the CSS component of this API, which is common to SPA/MPA, and the SPA specific JS API.
The rationale for skipping the transition was to make it easier for developers to spot an error with a hard failure rather than a graceful fallback which masks it. If the There are use-cases which need a common identifier for a set of tagged elements, discussion at #8209. This can be added in the future, we haven't designed ourselves in a corner here. Also worth noting is the design principle that Transitions are an enhancement, so we don't see skipping the transition as a failure. We might, on really low-end devices, or devices in some constrained mode, choose to always skip transitions.
Developers can override this with a style rule, similar to overriding any other rule in UA CSS.
It isn't clear what problem this solves, duplicate That said, your suggestion for distinguishing
A pattern I’ve seen to do this is toggling the class name on the root element: document.documentElement.classList.add(“transition-old”);
document.startViewTransition(() => {
document.documentElement.classList.remove(“transition-old”);
document.documentElement.classList.add(“transition-new”);
});
} html.transition-old .element-foo {
view-transition-name: target;
}
html.transition-new .element-bar {
view-transition-name: target;
} There are probably better ways to do this. Given that the author already has to time their DOM update in the callback passed to startViewTransition, it doesn’t seem like an issue to have to update
IMHO the API already requires minimal CSS for the common use cases. For a root transition which is a simple cross-fade, no CSS is necessary. For transitions morphing one widget into another, the developer needs to only add What we haven’t been able to do is a no JS syntax for basic SPA transitions. You need at least 1 line of JS to make that work: document.startViewTransition(updateToNewState); And that’s because any basic SPA app will drive DOM changes via JS internally. They will already have script which invokes updateToNewState along with mutations to the navigation history. So it doesn’t seem too difficult to wrap that call in the syntax above. We could consider invocations to So the minimal JS API is unavoidable for the same-document (SPA) API. The MPA API can be script free because these JS events are implicit in the navigation. A JS free API for same-Document transitions is definitely useful for a subset of cases but doesn’t need to be a goal for v1 of this feature.
I believe this is already the case. We had multiple breakout sessions with CSSWG during the early incubation period. Those sessions are recorded in #6464, which also includes WG’s resolution for the spec to go to FPWD. All non-trivial changes have gone through CSSWG resolutions as well. I’m happy to take suggestions for more engagement with CSSWG. |
Thank you for being responsive to our feedback. We circled back at this today in a breakout and we have consensus that our work here is done for now. We do have concerns about this API, discussed above, but are also optimistic that these are being worked out, and we do think this is functionality that is very useful for developers. We are looking forward to seeing how this API evolves to be more usable in a wider variety of use cases. We will close this for now, feel free to re-request a review if you make substantial changes. |
Wotcher TAG!
I'm requesting a TAG review of View Transitions.
View Transitions is a proposal for a new web API that allows a simple set of transition animations in both Single-Page Applications (SPAs) and Multi-Page Applications (MPAs).
The inspiration for this feature are transitions similar to the ones listed in the Material Design Principles. The intent is to support transitions similar to Android Activity Transitions.
Further details:
We'd prefer the TAG provide feedback as (please delete all but the desired option):
☂️ open a single issue in our GitHub repo for the entire review
The text was updated successfully, but these errors were encountered: