-
Notifications
You must be signed in to change notification settings - Fork 677
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
[css-view-transitions-2] Distinguish between old and new DOM in CSS #9424
Comments
In this case, wouldn't you have some other things in the old and new DOM that you can rely on? e.g. if you're moving between a home and article page, you'd probably have Can you expand, how you would use old & new in a way that's not achievable with regular selectors? |
I'll let @calinoracation clarify the use-case. |
For us we try to declare everything at the site that's triggering a transition. For example we might have the element Transition: Search -> Details
We would use the new syntax like this: .main-page-slide {
&:active-view-transition(main-page-slide):active-view-transition(--old) {
--screen-a_container: screen;
}
&:active-view-transition(main-page-slide):active-view-transition(--new) {
--screen-b_container: screen;
}
// other view transition related configuration for this transition
} document.startViewTransition({
update: updateTheDomSomehow,
classNames: ['main-page-slide'],
}); The main reason is that at Airbnb we're already seeing scaling issues with each component or route needing to know about every transition it needs to participate in. People clobber others or don't want the view-transition-name assigned in a certain instance. We've adopted a semantic naming approach, where instead of the callsite needing to know a name like Sidenote: I'm a bit confused on the naming of |
Thanks for the use case @calinoracation ! Curious: what happens inside your (using search and details instead of a/b, helps me feel closer to the use-case, hope that's ok) JS: function transitionToDetails() {
// mainPageSlide.dataset.current === "search"
document.startViewTransition({
update: () => {
// Start a react chain that ends up doing a lot of stuff but also:
mainPageSlide.dataset.current = "details";
},
classNames: ["main-page-slide"]
});
} CSS: html:active-view-transition(main-page-slide) {
.main-page-slide {
&[data-current=search] { --screen-search: screen; }
&[data-current=details] { --screen-details: screen; }
}
} Note that having this old/new feature would allow "ghost" view transitions - running a whole transition without changing the DOM at all by responding to class names + old + new, and resetting to the original state at the end. Not sure if this is a bug or a feature, but it's definitely a bit of an odd side-effect... In your case what you're trying to do is not a ghost transition, but rather a classic transition to a new state. By using the old/new idiom here, wouldn't you have to define the old/new state twice in some sense? |
For us the Yeah I prefer the actual use case of search to details, it's one of our most common flows! |
Yeah agreed on the ghost side-effect, but it sounds pretty interesting. We weren't trying to do that but if we ever had a CSS way to trigger a view transition then this side effect combined would make things very fascinating. |
It must do other things as well, no?
This pattern is an example, I'm suggesting to use whatever your DOM already exposes when you change screens.
It would be interesting, trying to understand if it's useful/needed by anyone... we can leave this issue open to see if that need emerges. |
@noamr Yeah Think a product details page that might be different for plus, lux, experiences, etc or search through different things. It might be in search or in a product details page or a details preview embedded in another screen. What we do know generally during the triggering of the transition is the general semantic elements. Since a target shared element can be in 20+ animations and continue to grow, it's hard to be certain about a specific DOM structure. That's why the old/new switch is so nice for us. That said, it's far from impossible. We make it work today. We do redefine startViewTransition to make this following snippet possible. ${Transition.map({ screen: '--screen-panel' })}
${Transition.map({
box: {
old: '--box-pdp',
new: '--box-checkout'
}
})} |
@calinoracation would you have a preference between a model that requires declaring old/new types when you trigger a transition vs setting the new types within the update callback? // If newType is specified, its used as types on the new DOM instead of type.
document.startViewTransition(updateCallback, {type: old, newType: new}); vs let vt;
async function updateCallback() {
...
vt.type = new;
}
vt = document.startViewTransition(updateCallback, {type: old}); Only reason we can think for the latter would be if some components execute script as a part of updateCallback() which you need to figure out the new type. But don't know if that's an issue in practice. The catch though is that timing is subtle to make sure types are updated at the correct spot so they apply when the browser decides view-transition-names in the new DOM. I'm unsure about whether the following would work for instance: vt = document.startViewTransition(updateCallback, {type: old});
vt.updateCallbackDone().then(() => {vt.type = new}); It requires a microtask checkpoint after updateCallback finishes and browser looks for names in the new DOM to ensure |
@khushalsagar For the use cases I can think of we'd always have a good idea of the old/new types at the time of triggering it. The only time it's not explicit from us is in handling back/forwards navigation. That's not too hard in this case though as I'd imagine we'd just swap out the
Is this allowed to be an array or just a single possible item on each call? Assuming the former due to naming but wanted to check. ${Transition.map({
box: {
old: '--box-pdp',
new: '--box-checkout'
}
})} From my example above, would now become something like this? document.startViewTransition(updateTheDOMSomehow, {
types: 'box-pdp',
newTypes: 'box-checkout',
}); |
Thanks for the feedback!
Its an array, you can see syntax details here. |
Since this is quite easy with const transition = document.startViewTransition(
{ types: ["old"], update: () => {
transition.types.remove("old");
transition.types.add("new");
// update the DOM somehow ...
}}); @bramus perhaps we should have some post about using |
#8960 adds the capability to add custom names to identify the transition which can then be used to conditionally apply styles. But it doesn't provide a way to specify whether a style rule applies only to the old DOM in a transition or only to the new. For example, with the following script:
:active-view-transition(main-page-slide
will apply from when startViewTransition is called to when the transition finishes. If you want add a name to an element in the old DOM but not in the new DOM, that still needs to be managed in script.One way to solve this is UA supplied class names: "--old" and "--new". Such that
:active-view-transition(--old)
applies after startVT is called and until the update callback is dispatched.:active-view-transition(--new)
applies when the update callback is dispatched and until the transition finishes. Then authors could combine this with their own class names:@noamr FYI.
The text was updated successfully, but these errors were encountered: