-
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] CSS only way to transition between list <-> detail views #8209
Comments
Just to clarify, the CSS property I'm supportive of having a class name like identifier which can be common to set of elements for the purpose of specifying styles which apply to a subset of pseudo-elements of a type but not all of them. So you'd have:
|
Could you apply both a class and a name at the same time? If so this may be enough. Given this transition: From HTML:
To HTML:
The transition would generate these pseudo-elements?
Which could be targeted with this CSS:
Does this look right? |
I think part of this problem would be solved by transitions 'classes' #8319. However, there's another part to this. If you have 50 list items, and one detail view, this will result in 50 transition groups, all but one outgoing. That's pretty bad for performance. #8282 might allow some culling, but it still isn't ideal. It seems like, in this case, we really want the developer to limit the transition to the single clicked thumbnail. I don't immediately see a way to solve this, as the browser won't know what's in the new state when capturing the old state. |
A
Implicit might not be the best API for a shared element list to detail transition, but would be very useful in many other cases. |
Are you suggesting that, an element with a |
You're right, they can't share a pseudo-element because, yes I propose that removal automatically trigger animation. In fact, I've confused pseudo-classes and pseudo-elements. Implicit element removal animation would need two pseudo-classes, like My hope was to piggyback onto your API and animate out using those pseudo-elements of yours. But I understand now that won't work, if it triggered your API or allowed a redundant way of styling. My experiments with discrete-state suggest that it might be possible to use live elements, and have the browser report discrete destination values only. Sorry for being sloppy, I'll be a lot more precise after implementing it. |
I don't know if it's what you're referring to, but you can create exit and entry animations with view transitions: https://developer.chrome.com/docs/web-platform/view-transitions/#custom-entry-and-exit-transitions |
We are running into the same for our list detail views. JavaScript has been our solution so far but it's not ideal. One thought I was pursuing was since it's generally a link or button triggering the transition, that I could use :has and :focus-within to add the view-transition-name to the item being opened. The other challenge with that though is the navigation back. I had to track which item was opened and ensure it was set, so that again required js. In a future world and spa a style container query and variable set before might help, but alas that's complex. Glad other solutions here are being explored.. |
@jakearchibald had an idea which came up in the context of MPA API exploration that could be relevant here. Having a global name for the Document (or DOM state in the SPA case) that can be used as a CSS media query to conditionally name things. Super rough sketch: // When navigating from index to details page.
document.startViewTransition(updateCallback, {old-state: "index", new-state: "item1"});
// When navigating back from details page to index.
document.startViewTransition(updateCallback, {old-state: "item1", new-state: "index"}); Which can then be used in CSS on the index page to apply names: /* Only name this item if we're navigating to/from this item's details page */
@media (view-transition-new-state: item1) {
view-transition-name: item;
}
@media (view-transition-old-state: item1) {
view-transition-name: item;
} I'm assuming setting the old-state/new-state when calling startViewTransition is feasible since updateCallback is bound to know where the navigation is going. |
Thought about this and am trying it out and I do think we have access to both old & new state at the time of calling start. Think this is a really solid pattern so far. Still am very curious how this might work eventually in a CSS triggered activation. |
I wonder if instead of addressing this as a view-transitions problem, we should look at this from the point of view of So given a list of mini-posters that goes to a maxi-poster: a.miniposter:is(:next, :previous) {
view-transition-name: poster;
}
h1.maxiposter {
view-transition-name: poster;
} As a side-benefit, this would also let us curate cross-document view-transitions based on incoming URLs: html:has(a#home:previous) {
// customize transition based on the previous URL being "home"
} |
I'm assuming the That would only work for a narrow set of cases. For example, you have a link underneath an image for the list entry. How do you tag that image element in this case? |
Yes. We can also call it
.item:has(a:next) img.poster {
}
// or
img:has(> a:last-clicked) {
} |
Ah, so with |
Yep! |
Ok, I got it now. I'm still unsure of how we're solving the back navigation. Say the user goes from list page to details page for a list item. Now they can either go back (by clicking the back button in the browser) or go to the home page (by clicking a link on the details page). You only want to tag the hero image on the details page if the user is going back to the list page. Going back to home page doesn't need the hero image to do an independent animation. How would the author set this up? |
Have been pondering about this for quite some time, but never got round to replying here. An alternative approach I was thinking of was to allow wildcards at the end of names and pseudos. .maxiposter {
view-transition-name: poster-*; /* Any view-transition-name starts with poster- may transition into me */
}
#miniposter-123 {
view-transition-name: poster-123; /* Can transition into .maxiposter as the vt-name has the correct prefix */
}
#miniposter-abc {
view-transition-name: poster-abc; /* Can transition into .maxiposter as the vt-name has the correct prefix */
}
::view-transition-group(poster-*) {
/* … */
} As for back navigations, I would expect the browser to run the animations that ran in reverse, as it knows what was clicked, what the scroll position was, etc. |
First of all, this is a somewhat different use case, it's not related exactly to list<->details. body:has(link.details:next) #maxiposter {
view-transition: poster;
} We have to figure out some details though, because in the case of "Back" several links could be "next" and also we have to have UA-back in mind. |
This doesn't solve the issue, you still have to capture many snapshots when clicking a link in the list page. |
Agreed, going to a page other than the list page is a different use-case. I mentioned it because if we have a proposal which can solve this and the list use-case, we'd favour that over a proposal which only helps with the list use-case. In the proposal below, the current Document needs to have link to the new Document in their html. It also looks like the presence of that link doesn't help narrow down which element to target. body:has(link.details:next) #maxiposter {
view-transition: poster;
} I'm evaluating this against the media query option: @media (next: urlpattern(...)) {
#maxiposter { view-transition-name: poster; }
} It seems like both would be functionally equivalent (do correct me if I'm missing a case). The media query one seems more ergonomic to me but I'd love dev feedback on that. |
This is great, though I would probably have something like @navigation details {
target: urlpattern(...);
auto-view-transition: same-origin;
type: navigate | back-forward;
}
However, your suggestion and the rule alternative would require a media-query per item in the list, unless there's some way to use extracted URL-pattern parameters in selectors, e.g.: @media (next: urlpattern(/details/:id)) {
.miniposter#{:id} {
view-transition: poster;
}
} Perhaps we need both? @navigation list-details {
target: urlpattern(/list), urlpattern(/details?id=:id);
}
@media (navigation: list-details) {
#maxiposter {
view-transition-name: poster;
}
.item:has(:next, :prev) .poster {
view-transition-name: poster;
}
} |
Had an offline chat with @noamr today. I realized I hadn't completely followed the problem of "a media-query per item in the list". If we only have the media query, then the author is forced to generate a rule for each item in the list. The problem gets worse with a list using infinite scroll. So I do like the idea of a pseudo-class which activates on a href if its link matches the outgoing URL. Noam had a nice suggestion of the pseudo-class building on top of the media query with something like: @navigation list-details {
target: urlpattern(/list), urlpattern(/details?id=:id);
}
a:navigating-to(list-details) .poster {
view-transition-name: poster;
} |
I’m thinking of a new pseudo to indicate “hey, this was the element that initiated the navigation” to solve this problem. I’m using a:last-active {
/* This applies to the link that activated a navigation */
} Using .overview .card:has(a:last-active) {
h2 {
view-transition-name: title;
}
img.hero {
view-transition-name: hero;
}
}
#detail {
h1 {
view-transition-name: title;
}
header img {
view-transition-name: hero;
}
} (This new pseudo is needed because the regular |
Personally would love if whatever route was chosen didn't require urlpattern, I feel like for a lot of use-cases those are driven from the server so it's hard to be sure of any specific pattern. Really like the option of the pseudo. I'm not sure it's a big deal but if someone handled a click event on a button (ie: form submission or action + redirect), then I'm guessing we'd not have a way to indicate that with the current proposed options. Again not huge as we typically favor anchors, but thought it'd be worth mentioning. |
With For example if going from |
I don’t think I fully understand the page flow. The idea for |
That makes sense. I guess I was hoping any solution would solve for user's back button or swipe navigation gestures as well. The Would their be an equivalent |
Currently, the spec only adds one new CSS property for all elements view-transition-name. This results in some awkward JS required to support transitions between a list view (of video thumbnails for example) and a detail view (of a video player) that has to add the right
view-transition-name
to the clicked thumbnail for transition into the detail view, and find the right thumbnail based on the video view.The list <-> detail views are a common enough use case that I think it warrants a way to address this in the API directly. One way this could be done in just CSS today would be to define a different
view-transition-name
for each element in the list and then use the same one for its detail view.This works fine if you can rely on the default transition, but if you want anything else, then you'll have to start adding rules for each of the transition names. This is not very scalable or desirable:
proposal
Introduce a new
view-transition-id
that can be paired withview-transition-name
to target and generate animations. CSS could then be written to target combination of name, name/id or name/any id. Eg:The UA would then have enough information to know how to animate the specific thumbnail into the video without needing any custom JS.
Obviously the exact syntax can be different than what I propose here. The important part is to have a way to match a "class" of elements, but still be able to differentiate them during the animation based on a unique id.
Thoughts?
The text was updated successfully, but these errors were encountered: