- From: CSS Meeting Bot via GitHub <noreply@w3.org>
- Date: Fri, 14 Nov 2025 03:06:59 +0000
- To: public-css-archive@w3.org
The CSS Working Group just discussed `[css-view-transitions-2] [scoped] What is the layout of the ::v-t pseudo in relation to the scope?`, and agreed to the following: * `RESOLVED: make the VT have a stacking context that's a sibling of the scope stacking context, but painted at a point before transforms/filters. Still a child of the scope.` <details><summary>The full IRC log of that discussion</summary> <TabAtkins> vmpstr: in scoped VT, reminder it's about VT running on subtrees, not just the document<br> <TabAtkins> vmpstr: setup is roughly the same, you just start the transition on an element, discover names in the subtree, create VT pseudos representing the transitioning parts of the subtree<br> <TabAtkins> vmpstr: for document VT we hoist the VT pseudos to the top layer so it can capture the document itself, too, and represent that in its pseudos<br> <TabAtkins> vmpstr: so we need an equivalent thing for elements. pseudos should be able to capture the hosting element's decorations/background/etc. can't be a child without it being circular<br> <JakeA> q+<br> <TabAtkins> vmpstr: so our idea is to have ::v-t pseudo-element be a next-sibling of the VT scope element<br> <TabAtkins> vmpstr: and then use anchor positioning to put it over top of the scope<br> <TabAtkins> vmpstr: this works pretty well for a lot of cases<br> <TabAtkins> vmpstr: one case where it doesn't<br> <TabAtkins> vmpstr: if the scope element is rotated or not axis aligned<br> <ntim> q+<br> <TabAtkins> vmpstr: anchor spec says the anchor box is the axis-aligned bounding box of the anchor<br> <JakeA> q-<br> <TabAtkins> vmpstr: there's a workaround, selfishly hoping the anchor spec can eventually allow positioned elements to be in the same positioned space as the anchor<br> <emilio> q+<br> <TabAtkins> vmpstr: so we'd like to go ahead with the current design of it being the next sibling, and just positioning it over<br> <astearns> ack ntim<br> <TabAtkins> ntim: from an impl pov, a bit worried about making the pseudo a sibling<br> <TabAtkins> ntim: might have implications in the Dom tree, sounds tricks<br> <TabAtkins> noamr: it's just in the layout tree, the box tree<br> <JakeA> q+<br> <JakeA> q-<br> <JakeA> q++<br> <TabAtkins> noamr: reproducing the doc VT case where the VT is in the top layer, a "sibling" to the doc<br> <astearns> ack +<br> <TabAtkins> emilio: is the idea that we don't want this in the top layer? we want it clipped by ancestors?<br> <TabAtkins> TabAtkins: yes, absolutely<br> <TabAtkins> JakeA: yes, in Shopify days we couldn't use VT in some cases because they wanted a VT on just a small piece of the page.<br> <TabAtkins> JakeA: they used VT:none on root to prevent that from animating, but then if they had a tooltip on top it would drop below the top-layer VT stuff, so they made *it* VT as well, whack-a-mole<br> <JakeA> astearns: doh, hah!<br> <JakeA> q-<br> <TabAtkins> emilio: if you have something in-flow, and you put something out of flow on top of it, that doesn't quite match the in-flow painting order.<br> <TabAtkins> emilio: it's painted by the abspos's CB, might be higher up<br> <kush> q?<br> <ntim> q+<br> <fantasai> TabAtkins: We've had some cases where we want to make it easier to select other containing blocks<br> <noamr> TabAtkins: we want to make it easier to select other containing blocks, e.g. your parent<br> <fantasai> ... in particular, your parent<br> <noamr> emilio: let's say you have a thing with overflow: clip and animating something inside of it. now you call startViewTransition on that. you effectively created an abs-pos on top. it would escape the clip<br> <noamr> emilio: clips of any ancestor from the scoped element to the nearest abs-pos<br> <noamr> TabAtkins: we want to enable it in the future<br> <noamr> emilio: sounds like it's a bit in the air<br> <emilio> ack emilio<br> <astearns> ack fantasai<br> <Zakim> fantasai, you wanted to comment on containing blocks<br> <TabAtkins> fantasai: I don't think anchorpos is the right solution for this<br> <TabAtkins> fantasai: you really do want to change the CB to this element. not by pos:rel, that is disruptive<br> <flackr> q+<br> <TabAtkins> fantasai: but we should have some way to say that the scope is the CB for that<br> <fantasai> https://www.w3.org/TR/css-position-4/#scrollable-cb<br> <TabAtkins> fantasai: some points to talk about why not do that. scorlling is one. we recently talked about three CBs generated by a scroller, one is the fixed CB, that's what you want<br> <TabAtkins> fantasai: so there are plans to add switches for that, should rely on that<br> <TabAtkins> fantasai: for the transform case, when you're contained by the transformed element you're in it so you're transformed with ti<br> <TabAtkins> vmpstr: the problem here isn't so much positioning, as trying to capture the effects on the scope itself<br> <emilio> q+<br> <TabAtkins> vmpstr: like a filter on the scope, the pixels you capture from that filter have to go into the VT pseudo-element. if that pseudo is also a child of the filter, then you're double-filtered<br> <TabAtkins> vmpstr: or circular if you want to prevent that<br> <flackr> not being filtered by the element, not being clipped by the element, etc<br> <TabAtkins> vmpstr: so it's less positioning, more about not being in the same filter tree/effect tree as the scope<br> <astearns> ack ntim<br> <TabAtkins> ntim: back to DOM mutations<br> <TabAtkins> ntim: say you move the scope element elsewhere in the tree. do you track the pseudo and move it at the same time?<br> <TabAtkins> ntim: otherwise you get z-order issues<br> <TabAtkins> TabAtkins: moving is a remove/add, so you cancel everything<br> <TabAtkins> JakeA: no, new method just moves it directly<br> <astearns> ack flackr<br> <TabAtkins> noamr: just need to make sure that's an issue we track<br> <astearns> ack emilio<br> <TabAtkins> flackr: yeah, confirming that this can't be a box child so we don't clip/filter it<br> <noamr> q+<br> <TabAtkins> emilio: I wonder, if you make this API parallel to the doc version, the doc version isn't in the doc itself, but the contents of the document<br> <TabAtkins> [not sure what that means or if I minuted it right]<br> <TabAtkins> emilio: instead of capturing the whole scope, you capture just the contents of the element, then the issue goes away<br> <TabAtkins> JakeA: my first draft did that, people just end up creating a wrapper div<br> <TabAtkins> vmpstr: we did consider that, but a very common use-case people do is "run on a div, change its background". but that won't work, background is part of the element itself not its contents<br> <TabAtkins> vmpstr: so we're really trying to make it so the scope itself is represented<br> <kush> q+<br> <TabAtkins> emilio: I wonder if we could define, rather than a sibling, it's a regular child but define special painting/capturing rules, in a VT the stacking context your box creates is in one place...<br> <TabAtkins> emilio: so the pseudo isn't a sibling in the box tree, but in the stacking context sense. one order that's for capturing VT, another for actual rendering<br> <TabAtkins> emilio: that solves layout issues, unsure if it adds more complications<br> <TabAtkins> emilio: but this is similar to what you do for the doc transition to capture the canvas background/etc<br> <TabAtkins> vmpstr: i'm not opposed to that, it's just more magic<br> <TabAtkins> vmpstr: it's more *explainable* with anchorpos, while this is pure magic. but I'm fine with that<br> <TabAtkins> noamr: initially this was my mental model, an anonymous container that holds the element and the VT pseudos<br> <TabAtkins> emilio: yeah, same way you can define the order in which stacking contexts are applied, you can define filter/transform/opacity, etc in a particular order to be correct. can define VT at a particular spot so it's outside the filters but within the element still.<br> <TabAtkins> noamr: only thing is it's less explainable in CSS terms<br> <TabAtkins> emilio: but still the same as the doc VT, yeah? doc transitions capture the canvas background, that's outside the document element. so I think this matches doc VT more closely.<br> <TabAtkins> emilio: if it makes the whole setup simpler should just do it<br> <TabAtkins> vmpstr: difficult part would just be describing transforms/etc. doc is affected by less than elements are.<br> <TabAtkins> emilio: sure<br> <TabAtkins> vmpstr: I think it's doable, just a little awkward<br> <TabAtkins> emilio: do you know off top of you head if transform is before or after filters?<br> <TabAtkins> emilio: [goes into a little more detail]<br> <TabAtkins> emilio: I find that model a bit easier, or more parallel to doc VTs<br> <TabAtkins> fantasai: makes sense to me<br> <TabAtkins> emilio: like if you apply filter to root, it doesn't just apply to root it applies to whole doc. but doc VT escapes that.<br> <TabAtkins> vmpstr: I also need to think through how the VT pseudos can be styled<br> <TabAtkins> emilio: same as in doc VT, the pseudo isn't affected by the VT styles<br> <kush> q-<br> <TabAtkins> JakeA: btw, it's filter *then* transform<br> <noamr> q-<br> <TabAtkins> emilio: so yeah that works, transform is applied on top after the VT is already positioned, so it follows along<br> <flackr> +1 that sounds like it could work<br> <fantasai> +1<br> <TabAtkins> astearns: so sounds like a different route. Vlad, do you want to explore implication in the issue, or just take a resolution?<br> <TabAtkins> vmpstr: might as well resolve, if we have issues we'll bring it back<br> <TabAtkins> vmpstr: resolution is to make the VT have a stacking context that's a sibling of the scope stacking context, but painted at a point before transforms/filters. Still a child of the box tree.<br> <TabAtkins> emilio: should we enforce the scope to be a CB for abspos? if you start a VT on a staticpos, the insets wont' work<br> <kush> q+<br> <TabAtkins> noamr: it's layout-contained, that already makes it a CB<br> <TabAtkins> kush: I was trying to understand - if it's a sibling in the box tree... sorry, a child, but it's painting involves all the content besides itself<br> <TabAtkins> kush: does it get the local clips?<br> <TabAtkins> emilio: probably not. ancestor clips apply, but on the element itself won't<br> <flackr> it should only be affected by the transform of the element<br> <TabAtkins> emilio: it'll be a painting layer defined,<br> <TabAtkins> kush: q is just if we make it a child of the scope, how many things that are inherited from the scope will have to be handled special<br> <TabAtkins> emilio: fair, but all those special things are what you want<br> <TabAtkins> kush: right, but we got all those special things for free by making it a sibling, they're manual now that it's a child<br> <TabAtkins> emilio: but many other things are easier as a child<br> <TabAtkins> vmpstr: what I think we really want is the scope to be the child of the VT<br> <TabAtkins> vmpstr: but that's... complicated<br> <TabAtkins> astearns: we're at time. should we not resolve yet?<br> <TabAtkins> kush: taking resolution seems fine for now, curious about what we'll learn impl wise<br> <TabAtkins> kush: i'm on the same side as Emilio, argued for that in my head, but other than moving the pseudo alongside the element, what am I gaining by the child approach rather than sibling?<br> <TabAtkins> emilio: you also get abspos CB for free, rather than it escaping all the clips up to its actual abspos CB<br> <flackr> +1<br> <TabAtkins> astearns: this is details. back to the question. objections to the proposed resolution?<br> <TabAtkins> RESOLVED: make the VT have a stacking context that's a sibling of the scope stacking context, but painted at a point before transforms/filters. Still a child of the scope.<br> </details> -- GitHub Notification of comment by css-meeting-bot Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/12324#issuecomment-3530620798 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Friday, 14 November 2025 03:07:00 UTC