-
Notifications
You must be signed in to change notification settings - Fork 707
[css-view-transitions-2] Proposal for a view-transition-tree property (name tbd) #10334
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
Comments
Thinking through an example: ScreenFlow.mp4In this case, the top box doesn't want to be contained, as it wants to transition between containers, whereas the other items need to be contained within the container. I can think of a couple of ways of doing this: Option 1: Manual grouping
So, for the above example: <div class="container-1">
<div class="card card-switching-containers" style="view-transition-name: card-1"></div>
<div class="card" style="view-transition-name: card-2"></div>
<div class="card" style="view-transition-name: card-3"></div>
<div class="card" style="view-transition-name: card-4"></div>
</div>
<div class="container-2"></div> And the CSS for the transition: .container-1 {
view-transition-name: container-1;
}
.card {
view-transition-parent: auto;
}
.card-switching-containers {
view-transition-parent: none;
}
html::view-transition-group(container-1) {
overflow: clip;
} This is a bit manual, as I need to set things up for this particular transition. Option 2: Auto groupingThe <div class="container-1">
<div class="card" style="view-transition-name: card-1"></div>
<div class="card" style="view-transition-name: card-2"></div>
<div class="card" style="view-transition-name: card-3"></div>
<div class="card" style="view-transition-name: card-4"></div>
</div>
<div class="container-2"></div> And the CSS for the transition: .container-1 {
view-transition-name: container-1;
view-transition-tree: preserve;
}
html::view-transition-group(container-1) {
overflow: clip;
} This case 'just works', because a given card won't be grouped within I wonder if there are cases this doesn't provide enough flexibility. If the tree goes from three groups Option 3: both?Allow option 2, but also allow individual children to assign themselves to a particular parent group. The assignment from the child would take priority. |
With
I don't have great suggestions on top of my head, but could the use cases be covered by scoped element transitions? e.g. making so running a document VT + a scoped element transition concurrently parents things accordingly? or having some API to run both at the same time? |
The circularity is a good point. Option 2 doesn't have that problem.
Interesting! But don't we run into all sorts of problems by trying to run two nested transitions like this? |
I agree that the circularity is a problem that needs to be solved for option 1 (which is why I haven't mentioned it, but did think about it). Auto grouping makes the example above awkward to express, since you need to modify your dom to encompass some things but not others. I like option 3, just have both: by default |
That's an excellent point Jake. We actually considered option 1 too but leaned towards option 2 because it avoids the possibility of circularity. The use-case you mentioned though is a good reason to go for option 1. We already know which names appear in the ancestor chain when we reach a named element, so its trivial to fix the circularity issue by simply ignoring the If we have to pick an option, the Re: mismatch in old and new DOM hierarchy, the situation can happen with either syntax option. We can consider a couple of options:
Excellent question! The use-cases we've seen do involve a full page transition. Think clicking on a button which expands to a widget while the background changes. This kind of thing is harder to coordinate with 2 independent transitions. We also have to think through how to deal with resizing for scoped transitions. For the scoped element, its layout for the end state will keep changing as its resized. That said, @jakearchibald's example of a subset of nested elements being clipped can't be solved with scoped transitions. When a scoped transition is started, only elements in the subtree of the scoping element can participate in that transition. Content inside the scoping element can't animate out of it. For this you do need a transition at the root but with nested |
FWIW, I prefer keeping the old dom structure. So in exit or paired animations, the old state determines the structure. For entry animations, the new state determines where to attach the entry groups. It's simple and I suspect most of the time works for reasonable effects |
SGTM! @jakearchibald @nt1m do you see any issues with this approach? |
The other way around, no? |
I don't think I fully understand what's being proposed here. In this example: <div class="container-1">
<div class="card" style="view-transition-name: card-1"></div>
<div class="card" style="view-transition-name: card-2"></div>
<div class="card" style="view-transition-name: card-3"></div>
<div class="card" style="view-transition-name: card-4"></div>
</div>
<div class="container-2"></div> And the CSS for the transition: .container-1 {
view-transition-name: container-1;
view-transition-tree: preserve;
}
html::view-transition-group(container-1) {
overflow: clip;
} If |
The proposal is to keep it in the structure where it appeared in the old state. So if both ::view-transition
|__ ::view-transition-group(root)
|__ ::view-transition-group(container-1)
| |__ ::view-transition-group(card1)
| |__ ::view-transition-group(card2)
|__ ::view-transition-group(container-2) In other words, even though the card moved in the "new state", in the "old state" it's still a part of With the clip, it means that the card will "disappear" as it tries to slide out of |
Yup. Sorry, fixed the comment above.
What @vmpstr said. In the case above, you want |
Our use case typically would benefit most from Option 1. We do have cases like @jakearchibald demonstrates in #10334 (comment) where we move an item from 1 container to another, and we want to contain the items moving to the second container that might be in a another tree. Here's an example where we move a group of items from 1 container to the other. We'd definitely use the 80ec9e897c407837b4a0761ad3037299.mp4I did have another use-case that I've been curious about, if we have the |
Can you expand a bit more on what you mean by "access to underlying data"? I suspect you already have the bits you need via |
Oh, I didn't realize we could do that, yeah actually nevermind then, that's perfect. I think the primary issue with that would be say if it was access to dimensions of a parent that are animating to a new size, but that should be covered by the |
Evaluating how There shouldn't be an issue with the .card {
--card-id: element-uuid();
view-transition-name: ident(var(--card-id));
img {
view-transition-parent: ident(var(--card-id));
view-transition-name: ident(var(--card-id) "-img");
}
} But I don't see how |
Proposed resolution to go with option 3 from the comment above: #10334 (comment). One question, what should happen if the author adds The pro of requiring @jakearchibald @calinoracation any suggestions? |
Can you elaborate on the reasons? Requiring |
It's mostly this use-case: "I have a list of cards in a container and only one of them needs to be parented to that container". Adding
The author can get this behaviour by using
Good question. Anchor positioning does require a |
One approach would be to make .container {
view-transition-name: container;
view-transition-tree: preserve;
view-transition-parent: none;
}
.special-item {
view-transition-name: special-item;
view-transition-parent: container;
}
.other-item {
view-transition-name: other-item;
/* view-transition-parent: none is inherited from .container */
} I think whether or not I guess a counter example to inheriting is also the above case where the container wants to escape its parent, but all the children should be auto. The only way to do that is something like the following: .container {
view-transition-name: container;
view-transition-tree: preserve;
view-transition-parent: none;
}
.container > * {
view-transition-parent: auto;
} which seems unintuitive |
We don't need it to be an inherited property for this. A simple descendant selector will do it, though it reads kinda awkward. .container {
view-transition-name: container;
/* Parent all named children to me. */
view-transition-tree: preserve;
}
.container * {
/* Actually, don't. */
view-transition-parent: none;
}
That's true! I'm not sure about this: "since if an element wants to have a different parent, presumably all its children by default also want to have that parent?". I expect the common case would be for that element's children to be parented to it. Something like:
In fact since the proposal above is for |
One thing I’m not entirely convinced of is the fact that the containers in the given example need to have a Maybe there could be a way to mark element to become a “view transition container” that automatically clips its participating contents without the container itself moving around or stuff? I’m leaning towards CSS Containment for this.
Setting |
So if the element is container only, it's painted content draws into its ancestor's snapshot (as usual) but there is a group pseudo-element generated to mirror its geometry and parent its descendant named elements. If the goal is just to optimize out redundant snapshots, then the browser can do this automatically. If the container has no painted content, we optimize out its snapshot. So I'm hesitant to add this paradigm unless needed for a use-case, for example, the element has painted content which needs to draw into its ancestor instead of underneath its own group pseudo. |
I've heard several requests for this. E.g. https://x.com/spinbutton/status/1792914789452140789?s=46&t=0fEqkKvBXH87vG_Sqv-Tbg |
Sorry I didn't mean use-cases for the feature itself. It's for an approach where requiring a name on the container wouldn't work because the author didn't want to lift the container's painting from its ancestor, just a group pseudo to mirror it's box. |
Somewhat related to @bramus' point: ScreenFlow.mp4The items in the container are clipped by the container's content box. But, if the developer puts Maybe the structure needs to be:
Where |
That's what I understood as well and why it seems doable. We generate a pseudo hierarchy based on the old state and a group might move higher in the pseudo ancestor chain based on new state. |
We would then have a common root from which to reference the transform. There's still work to recompute the old transform by accumulating ancestors until the new root, which should all be available as well. The new transform would also be relative to this element, which makes the animation make sense I guess we'd miss something like an ancestor filter on a group but that's probably not a common effect. I'm trying to weigh this solution to another one where the old state would keep the old image and the new state would keep the new image and have the transform there (I forgot who proposed this in an internal sync, apologies). The duplicating approach seems complicated and also doesn't solve all of the use cases (mix-blend-mode: plus-lighter for e.g.) All in all, I'm happy with lowest common ancestor approach |
@noamr One potential issue I see with that is we've typically relied on the How would we work around that as far as letting people still differentiate when something has been split into exclusive groups or if it really was just entering or exiting? |
It's not exactly an exception, I see these as actual exit/entry transitions, except there is some default relationship (e.g. the default transform animation would map to the same position on the screen)
One way is to not use this feature of mismatching groups :) It's a totally optional thing and an author can mandate using a common ancestor or flat tree etc. Are these mechanisms sufficient perhaps? |
What if, by default, the old+new yellow were drawn in both blue and green? That would result in the same animation as if no clipping was applied. To get to what you (Noam) are suggesting, there could maybe be an extra property to indicate that authors only want the old pseudo in the outgoing (blue) column and the new pseudo in the incoming (green) column. |
That's identical to using the common ancestor though, and the effect would be abrupt: right at the start in the animation the clipping would be gone. If that's the default animation we want, we should default to the common ancestor.
I guess what I'm saying is that you can already achieve the previous effect (by using the common ancestor) and mismatching parents is that extra property. It's a bit of an odd one to declare in your CSS so I think it's OK if it creates an animation that's different from the other ones. |
Sorry I wasn't clear here: I meant it would have the same animation (movement of the group, cross-fading of old+new) as in the current no-clip scenario, but the groups would still be clipped by the green/blue groups. (Not sure if that makes it more clear though 😅) |
Oh you mean do the split as suggested, but duplicate the snapshots to be both old and new? |
This specifies the new 'view-transition-group' CSS property and how it used, with some overview and an initial example. Based on [this resolution](w3c#10334 (comment)). There are still a lot of open issues but we will open them separately to avoid inflating the initial issue. Closes w3c#10334
This adds the initial runtime flag & property parsing, as specified in the CSSWG resolution: w3c/csswg-drafts#10334 (comment) This only deals with parsing as a custom ident, will add the keywords, rendering etc. in subsequent CLs. ChromeStatus: https://chromestatus.com/feature/5162799714795520 I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/iG4WDZOOzxY Bug: 347947051 Change-Id: I102c2d4e35efd305a6d43af7bfbbeb81b68a8393
This adds the initial runtime flag & property parsing, as specified in the CSSWG resolution: w3c/csswg-drafts#10334 (comment) This only deals with parsing as a custom ident, will add the keywords, rendering etc. in subsequent CLs. ChromeStatus: https://chromestatus.com/feature/5162799714795520 I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/iG4WDZOOzxY Bug: 347947051 Change-Id: I102c2d4e35efd305a6d43af7bfbbeb81b68a8393
This adds the initial runtime flag & property parsing, as specified in the CSSWG resolution: w3c/csswg-drafts#10334 (comment) This only deals with parsing as a custom ident, will add the keywords, rendering etc. in subsequent CLs. ChromeStatus: https://chromestatus.com/feature/5162799714795520 I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/iG4WDZOOzxY Bug: 347947051 Change-Id: I102c2d4e35efd305a6d43af7bfbbeb81b68a8393 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5741509 Reviewed-by: Khushal Sagar <khushalsagar@chromium.org> Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org> Cr-Commit-Position: refs/heads/main@{#1336513}
This adds the initial runtime flag & property parsing, as specified in the CSSWG resolution: w3c/csswg-drafts#10334 (comment) This only deals with parsing as a custom ident, will add the keywords, rendering etc. in subsequent CLs. ChromeStatus: https://chromestatus.com/feature/5162799714795520 I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/iG4WDZOOzxY Bug: 347947051 Change-Id: I102c2d4e35efd305a6d43af7bfbbeb81b68a8393 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5741509 Reviewed-by: Khushal Sagar <khushalsagar@chromium.org> Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org> Cr-Commit-Position: refs/heads/main@{#1336513}
This adds the initial runtime flag & property parsing, as specified in the CSSWG resolution: w3c/csswg-drafts#10334 (comment) This only deals with parsing as a custom ident, will add the keywords, rendering etc. in subsequent CLs. ChromeStatus: https://chromestatus.com/feature/5162799714795520 I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/iG4WDZOOzxY Bug: 347947051 Change-Id: I102c2d4e35efd305a6d43af7bfbbeb81b68a8393 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5741509 Reviewed-by: Khushal Sagar <khushalsagar@chromium.org> Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org> Cr-Commit-Position: refs/heads/main@{#1336513}
…arsing, a=testonly Automatic update from web-platform-tests Nested view transition: runtime flag & parsing This adds the initial runtime flag & property parsing, as specified in the CSSWG resolution: w3c/csswg-drafts#10334 (comment) This only deals with parsing as a custom ident, will add the keywords, rendering etc. in subsequent CLs. ChromeStatus: https://chromestatus.com/feature/5162799714795520 I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/iG4WDZOOzxY Bug: 347947051 Change-Id: I102c2d4e35efd305a6d43af7bfbbeb81b68a8393 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5741509 Reviewed-by: Khushal Sagar <khushalsagar@chromium.org> Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org> Cr-Commit-Position: refs/heads/main@{#1336513} -- wpt-commits: 7e07301489bcf1acecd2b5297232b042fe10ea64 wpt-pr: 47400
…arsing, a=testonly Automatic update from web-platform-tests Nested view transition: runtime flag & parsing This adds the initial runtime flag & property parsing, as specified in the CSSWG resolution: w3c/csswg-drafts#10334 (comment) This only deals with parsing as a custom ident, will add the keywords, rendering etc. in subsequent CLs. ChromeStatus: https://chromestatus.com/feature/5162799714795520 I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/iG4WDZOOzxY Bug: 347947051 Change-Id: I102c2d4e35efd305a6d43af7bfbbeb81b68a8393 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5741509 Reviewed-by: Khushal Sagar <khushalsagar@chromium.org> Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org> Cr-Commit-Position: refs/heads/main@{#1336513} -- wpt-commits: 7e07301489bcf1acecd2b5297232b042fe10ea64 wpt-pr: 47400
…arsing, a=testonly Automatic update from web-platform-tests Nested view transition: runtime flag & parsing This adds the initial runtime flag & property parsing, as specified in the CSSWG resolution: w3c/csswg-drafts#10334 (comment) This only deals with parsing as a custom ident, will add the keywords, rendering etc. in subsequent CLs. ChromeStatus: https://chromestatus.com/feature/5162799714795520 I2P: https://groups.google.com/a/chromium.org/g/blink-dev/c/iG4WDZOOzxY Bug: 347947051 Change-Id: I102c2d4e35efd305a6d43af7bfbbeb81b68a8393 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5741509 Reviewed-by: Khushal Sagar <khushalsagar@chromium.org> Commit-Queue: Noam Rosenthal <nrosenthal@chromium.org> Cr-Commit-Position: refs/heads/main@{#1336513} -- wpt-commits: 7e07301489bcf1acecd2b5297232b042fe10ea64 wpt-pr: 47400
View transitions right now construct a tree of pseudo elements that in some sense "flattened". That is, each
::view-transition-group
is a direct child of::view-transition
, which is a pseudo child of:root
. This allows some nice effects where each piece of a transition moves independently.However, there is also desire to have some relationship between the constructed groups.
Essentially what we want is for some elements to maintain their hierarchical relationship, where a
::view-transition-group
can have another::view-transition-group
as a child.The proposal is to add a new
view-transition-tree
property that takes two values:flatten
andpreserve
. This property would only have an effect if aview-transition-name
is also specified.The
flatten
value would be the default value and act as it acts today, the element on which this appears does not affect how the view transition descendants are constructed.The
preserve
value would act as a sort of a "containing block" for the view transition descendants: all of the descendants would be nested under their nearestpreserve
ancestor.All of the names are bikesheddable, of course
/cc @nt1m @khushalsagar @noamr @jakearchibald
The text was updated successfully, but these errors were encountered: