w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 661 forks source link

[css-view-transitions-2] Support View Transitions on a DOM subtree #9890

Open khushalsagar opened 9 months ago

khushalsagar commented 9 months ago

Currently View Transitions are Document scoped, there can only be 1 transition at a time and it runs in a layer which paints on top of the entire Document. A common feature request is to be able to run these transitions within the scope of a DOM subtree like:

document.getElementById(foo).startViewTransition(updateFoo);

Adding Agenda+f2f to introduce rough ideas on the rendering model for this.

bramus commented 9 months ago

A while back I ran a poll (Twitter, Mastodon) asking authors what is missing from View Transitions. Out of the 33 replies, 6 requested this feature, making it the number 1 request (along with retargetable transitions and auto v-t-name generation)

astearns commented 8 months ago

archived presentation: https://lists.w3.org/Archives/Public/www-archive/2024Feb/0000.html

css-meeting-bot commented 8 months ago

The CSS Working Group just discussed [css-view-transitions-2] Support View Transitions on a DOM subtree.

The full IRC log of that discussion <khush> https://docs.google.com/presentation/d/1yi1ynyk8cidWPY6L6Io4Al0IS6rQ8lGjQSZIZtgdPlw/edit?usp=sharing
<TabAtkins> khush: This is about an extension we're epxloring for VT
<TabAtkins> khush: other than cross-doc, this is one of the most requested features from authors
<TabAtkins> khush: fundanemtnal characteristic of how VT work today is they're global
<TabAtkins> khush: you're doing full-page changes in single-page apps
<TabAtkins> khush: as a result, you have all these limitations
<TabAtkins> khush: if a third-party widget is doing a dom change, it can't do VT without affecting your whole doc
<TabAtkins> khush: during VT you'll get a stacking content that draws on top of whole doc
<TabAtkins> khush: while your callback is running to update the DOM, all animations in the page will stop
<TabAtkins> khush: common scenario is a you click a button, widget comes up, shows a spinner while it loads. you'll notice the spinner pause now
<TabAtkins> khush: third issue is document becomes non-interactive
<TabAtkins> khush: if you have multiple stories all wanting to load up a VT, they're all noninteractive
<TabAtkins> khush: and finally you only get one transition at a time
<TabAtkins> khush: have to manually queue them
<TabAtkins> khush: but conceptually these are all independent
<TabAtkins> khush: today, to hack around this you have to insert an iframe. two iframes cant VT independently, at least theoretically. (but in chrome it depends on whether your iframe is OOP or not, and it's super heavyweight and bad)
<TabAtkins> khush: so hope is to address all fo these
<TabAtkins> khush: [shows simple dom]
<TabAtkins> khush: outer element wants to be part of the root transitions
<TabAtkins> khush: inner only wants to transition in the scoped-root
<TabAtkins> khush: so like if you ahve a page with a list of stories, you can have a root transition where all stories are sliding in, and scoped is each story animating itself internally
<TabAtkins> khush: so new proposal is view-transition-scope, saying this subtree establishes a scope, and scoped VTs can occur in it
<TabAtkins> khush: on the script side you grab a ref to the DOM you want, and use the normal API.
<TabAtkins> khush: so instead of only being able to start a VT form the Document, you can put it on any element
<TabAtkins> khush: [shows pseudo DOM]
<bramus> q+
<TabAtkins> khush: what w'ere trying to design now is what the node tree looks like
<TabAtkins> khush: idea is, if you have a VT tree rooted at doc righ tnow, you'll have a similar one rooted at the scoping element
<TabAtkins> khush: Here, the inner can contribute to the root or to the scoped VT
<TabAtkins> khush: We generate an image that can plug into the ancestor's transition
<TabAtkins> khush: the scoped root has "inner" as one group, for child elements participating in it
<TabAtkins> khush: So v-t-scope property says names that only exist in this node participate only in the scoped subtree's VT
<TabAtkins> khush: Today, if you use an iframe to do the nested VT, this is what th enode tree looks like
<TabAtkins> khush: so it's consistent
<TabAtkins> khush: some challenges
<TabAtkins> khush: isolating vt names, this is what v-t-scope is about
<TabAtkins> khush: It would be awkward to have a single leement painting at multiple spots
<astearns> q+ to ask about iframes as an alternative to this
<TabAtkins> khush: weird to have it display at multiple places in the screen
<TabAtkins> khush: so the names are isolated both syntactically, but also fundamentally, you can only participate in your nearest scoped ancestor's transition
<TabAtkins> khush: also, you can async update the DOM. a lot of frameworks authors integrate with don't support a sync update to the DOM.
<TabAtkins> khush: if possible we'd like to make that still work in scoped transitions
<TabAtkins> khush: so while you're updating the tree, browser has to display *something*. thinking is we want to display the old screenshot
<TabAtkins> khush: sort of a content-visiblity mode - as soon as the brower captures a screenshot, it keeps displaying that while the tree is updated underneath
<TabAtkins> khush: if your dom tree is in an intermediate state, you probably dont' wnat that to change the size of the element. so probably some sort of containment is needed. more research here.
<TabAtkins> khush: last challenge is about resizing. what happens when your scoped element's box resizes? image doesn't match the original size it was captured at, but it has to fit in the resized box
<TabAtkins> khush: some ideas - we should probably generate the pseudo-dom early
<TabAtkins> khush: today, the first frame fo the pseudo-dom matches exactly what th eold content looked like
<TabAtkins> khush: so continuing tha tmodel, we probably want the old appearance to immediatley show up in a pseudo
<TabAtkins> khush: also right now when we capture an element, we put all the box decorations (background, shadow, etc) in the image
<TabAtkins> khush: but here we're treating the scoped root's image as only its contents
<TabAtkins> khush: it's more like the scoped root's decorations are part of its ancestors context, not itself, so it can resize nicely
<TabAtkins> vmpstr: for v-t-scope Bramus suggested it be a container type instead of a new property
<TabAtkins> vmpstr: not set on a particular approach yet
<miriam> ack bramus
<emilio> q+
<TabAtkins> bramus: yes, this is #1 author request
<TabAtkins> bramus: second is name of the property. we have anchor-scope and timeline-scope already, i don't think name fits with these. more about isolation or containment.
<miriam> ack astearns
<Zakim> astearns, you wanted to ask about iframes as an alternative to this
<TabAtkins> astearns: in the tree slide, you mentioned this is the same structure you'd get in an iframe
<fantasai> so you're suggesting view-transition-container instead of view-transition-scope?
<TabAtkins> astearns: is that just sufficient? use iframes if you want scoped elements
<TabAtkins> khush: with iframes, the element resizes... we took a shortcut so if the iframe resizes we just skip the transition
<bramus> qq+
<TabAtkins> khush: the other thing is that a lot of other problems i mentioned, even with same-process iframes, impl internally is not able to support it
<TabAtkins> khush: so this is more like - if people start using iframes they'll still run into a lot of problems, so we need to solve them properly anyway
<TabAtkins> khush: what we're seeing is that people are just avoiding this use-case despite really wanting it
<TabAtkins> khush: [describes a problem with iframe impl today]
<miriam> ack fantasai
<Zakim> fantasai, you wanted to react to astearns to say this is presentational, shouldn't force weird document structures
<flackr> q+
<TabAtkins> fantasai: this is a presentational effect, it shouldn't force us to restructure the entire document relationship
<bramus> https://front-end.social/@bramus/111800601352108818
<miriam> ack bramus
<Zakim> bramus, you wanted to react to astearns
<TabAtkins> bramus: Here's an example I made, a header that expands and contracts as you scroll the page
<TabAtkins> bramus: if you were forcing author to put the header into an iframe wouldn't work
<TabAtkins> bramus: like the back button is part of the header
<miriam> ack emilio
<TabAtkins> emilio: so you'rea dding this to Element (or HTMLElement?)
<TabAtkins> emilio: several restrictions - needs to be a paint container, or something
<TabAtkins> emilio: any restrictions on the element that you call the API on? the scope element?
<TabAtkins> emilio: Another question is, how do you handle dom mutations?
<TabAtkins> emilio: Like if the dom moves around do you skip the transition, or do you just keep animating the pseudos as if they were there?
<TabAtkins> khush: for first q, there's an open questin about what sort of containment is needed
<TabAtkins> khush: today with VT, main one we landed on was if you put 'name' on osmething it needs to be a stacking context
<TabAtkins> khush: so we just applied those when you added a name (rather than requiring them for it be valid)
<TabAtkins> khush: we'd so similar here, add the restrictions if you do scope
<TabAtkins> khush: for second, today if you do transition on root and the element goes away, i think we skip the transition
<TabAtkins> khush: so this isn't a new problem
<TabAtkins> emilio: kinda is
<TabAtkins> emilio: iiuc, you animate its contents - or is it just any element insdie the scope?
<TabAtkins> khush: are you asking about when the scope root resizes?
<TabAtkins> emilio: so if you hav e scope root, and elements inside it animate, it seems like with this proposal you snapshot the elements that animate.
<TabAtkins> emilio: with documetn VT, you have the problem of element going away, but not with it moving elsewhere. it's always in the scope.
<TabAtkins> emilio: so what happens if the VT'd element moves out of its scope
<TabAtkins> vmpstr: the border-box vs contents is just the root itself (the scope root)
<TabAtkins> vmpstr: so you're asking if there's a VT'd node inside and it moves outside the scope
<TabAtkins> vmpstr: for the element inside the root, we'll capture the hwole thing (including decos)
<TabAtkins> vmpstr: if it moves out of the root, good question. we could treat it like it disappeared - fade it out? or just skip the transition
<TabAtkins> emilio: it's fine if it's TBD
<TabAtkins> noamr: the element moving causes it to dom-disconnect, makes sense to me that the transition gets skipped
<miriam> ack flackr
<TabAtkins> flackr: i think applying the restrictions we need at the point we start the transition is consistent with other animations things, like when we apply will-change
<TabAtkins> flackr: i think there's good answers for dom moving, but it's not as simple as skipping - if it's a child of the root you expect it to be able to move aorund
<TabAtkins> flackr: this proposal also shows how you do this with an imperative JS. is there a declarative equiv?
<TabAtkins> flackr: can I set some CSS rpoperty and have it start a scoped VT when I change the contents?
<TabAtkins> flackr: or what would that look like?
<TabAtkins> vmpstr: This is currently just an extension of the script API, easing the "only global" restriction.
<TabAtkins> vmpstr: the feature you're describing is a litle orthogonal, but could be enabled by this work
<TabAtkins> vmpstr: declaratively saying "this element animates when anything about it changes"
<TabAtkins> khush: this has been on the wishlist for a long time, someone pointed out changes on :hover
<TabAtkins> khush: fundamental issue is, when we realize you want to transition you've alread ymutated your dom
<TabAtkins> khush: we don't get an oppotunity to capture the old appearance
<TabAtkins> khush: that's why the JS version has you inform the browser to capture beforehand
<TabAtkins> khush: so that's why it's been harder to solve, but it's on our wishlist
<TabAtkins> bramus: i've also gotten the request from authors, but it's outside the scope
<TabAtkins> miriam: any resolution?
<TabAtkins> khush: no just feedback
<TabAtkins> miriam: okay, we're at lunchtime and there's no queue