W3C

– DRAFT –
Cascading Style Sheets (CSS) Working Group Teleconference

15 March 2023

Attendees

Present
bkardell_, castastrophe, chris, chrishtr, dbaron, dholbert, emeyer, emilio, fantasai, flackr, futhark, JakeA, jensimmons, jfkthame, lea, masonf, miriam, PaulG, rachelandrew, Rossen_, vmpstr, ydaniv
Regrets
-
Chair
-
Scribe
emeyer

Meeting minutes

View Transitions

[css-view-transitions-1] Capturing fragmented elements

github: w3c/csswg-drafts#8339

JakeA: When an element is captured as part of a transition, we ignore all the transforms and then figure out what transforms we need to apply to place it correctly
… so if the transition is a 90 deg rotation, you get a rotating transition
… The columns case is particularly interesting because you can apply transitions across fragments, which transitions each fragment individually
… That’s not compatible with the View Transitions model, which we want to be a single image and single transform
… It’s unclear to us if View Transitions are desirable in fragmented cases
… Prior art indicated fragmented elements should be treated as if joined flush
… We looked at Firefox’s implementation; it seems to capture the union of the fragments before a transition is applied

TabAtkins: That’s per-spec

JakeA: Good to know Firefox is doing the right thing

khush: I was confused bewtween what old specs said and what Firefox does

TabAtkins: The capturing of dimensions is spec-compliant; other things may not be

JakeA: Trying to figure out View Transitions in this case
… Option 1: You Are Not Allowed; the captured element must not fragment, which means you skip to the end of the transition
… Is a constraint broken when an element fragment, or if an element ever can fragment
… Previous resolutions have been that if a constraint can be broken, then the treatment is as if it has been broken
… If you’ve given a name a none-none value, should it prevent an element from being fragmented?
… Option 2: View Transition only applies to the first fragment; doesn’t seem useful, but could be done
… Option 3: Take a bit from the element() function and remove any transform from the elemenbt, figure out union of fragment quads, reapply transform to each fragment and capture image with that transform baked in
… Not sure if that’s useful, but it’s a non-failing treatment
… We’re stuck here.

vmpstr: One of the constraints we have is that the element has a box, so we don’t check if the element can lose its box; we only care whether it has a box
… I prefer option 1, because as you said this adds a lot of complexity to both model and implementation
… I don]t think there are compelling use cases to transition a fragmented element
… You could work around by putting a box around the fragmented element

<khush> +1 to Vlad's comment.

TabAtkins: I also think Option 1 is probably the right idea

<dbaron> +1 to not doing something complex if there aren't actual use cases for it. (I think that most strongly says "not Option 3".)

TabAtkins: none of the options are great, but I don’t think there is a good way to do it
… I think making thing with view transitions not-fragmentable makes sense

<astearns> also disagree with making things non-fragmentable

fantasai: The problem is a people will apply this to a lot of elements and if you force things to be not-fragmentable they’ll break in print
… I would just not go down this path; the problem here is the combination o f fragmentation and transforms
… if you capture the bounding box and say this is a the view transition snapshot, that’s okay

<Zakim> dbaron, you wanted to react to TabAtkins

dbaron: We seem to be focused on Tab’s variant of Jake’s option 1, not the original option 1

astearns: I think we’re agree Tab’s variant is Right Out

<khush> I'd be ok with that. Ignore the element if it fragments.

<TabAtkins> It feels a little unpredictable, but I think I'm okay with the "just don't VT if it's fragmenting"

fantasai: We could not transition when fragmented, or take the bounding box and transition the whole thing, which will interact weirdly with transforms

astearns: I’m fine with not transitioning view-fragmented things, but I’m concerned this is like other things we’ve punted for being too complicated and then never got back to

<fantasai> fantasai^: but would let you do simple transitions like translations or fades

astearns: We already have the optoin to apply a view transition to multiple elements, so we could treat fragmented elements as if they created separate view transitions

JakeA: The difficulty there is how you’d address each fragment with CSS, and what do you do if the number of fragments changes

astearns: I wouldn’t expect being ablke to address each fragment directly, until we have fragment pseudos (which we have talked about)
… As in regular view transitions, if you have an element that appears in one state but not the other, it doesn’t participate

florian: I agree with dbaron and fantasi
… Another concern: a user agent that’s interactive but paginates is not common today, but there are things like e-readers that could do that, and we don’t want a model incompatible with that
… It’s hard to make a union of things that don’t share the same coordinate space, like columns

TabAtkins: That union of non-oriented coordinate spaces is why element() stitches them together
… line-box-clamp could intersect with this; it’s at least fragmentation-adjacent
… I think option 2, transitioning the first fragment, is the best choice
… I think it’s better to get some of the element rather than none of the element during a transition

astearns: If we fragment the first box, we’ll find out if people want other fragments to transition

JakeA: Different transitions names for different fragments would be a nice way to address that

jensimmons: +1 to actually solving this and taking it seriously
… I can see a future where simple and elegant transitions make it so web sites use a lot of transitions to go between pages and even sites

<chrishtr> +1 to solving both

<fantasai> "using overflow fragments to solve the regions use case"

jensimmons: We also need to figure out overflow fragments to solve the Regions use case, and make ihs and view transitions work together

JakeA: I would worry that because we don]t know how the regions thing will work, we might pick a solution today that clashes

khush: As an implementor, if we ignore a fragmented element, the fallback is you get a crossfade rather than a nice animation
… I think I prefer we either ignore the element if it’s fragmented, or we use the first fragment, I’d be okay with either
… Doing a union like element() does, we could try, but I really want to see how that pans out

fantasai: If we take option 2 and go back to Alan’s idea, we could apply the same transition to all the fragments that is being applied to the first fragment
… In the future, we might be able to address each fragment individually, through something like :nth-fragment
… I think Alan’s proposal is the best going forward, but it’s not the easiest to implement
… We could start with first-fragment use, and leave the door open to individual-fragment later

khush: I think the problem is the View Transition API has a way to address fragments individually

fantasai: The selector would select all of them

JakeA: We could ask for the devloper to give view transition names to each fragment, and we could ignore in the meantime

fantasai: The whole element has a name, and we could use :nth-fragment

???: Would that mean the pseudo representing these elements is itself fragmented?

<JakeA> vmpstr:

fantasai: I’m not sure of the distrinction

vmpstr: So the new selector would select both, but they would be their own fragments?

JakeA: My understanding is if you give a name to an element, we’ll operate on the first fragment, but we can use :nth-fragment to address fragments?

fantasai: You can transition an <article> element, and then transition that element
… Each fragment gets snapshotted

JakeA: So what happens if you give an individual fragment a view transition name?

fantasai: I suppose you could do that

astearns: I like the idea of individually transitioning fragments, but don’t know if it’s useful to do before we have fragment pseudos
… That seems like the path forward

<flackr> I think the ideal would be if you have an element that has n fragments transition to another element with n fragments it pairs them up?

astearns: Not transitioning fragmented elements is a way of saying we’ll address this in the future, but don’t want to have a suboptimal solution now

JakeA: I like it

astearns: Any arguments that it would be better to transition the first fragment, rather than none?

(silence)

<JakeA> +1

<khush> sounds good

astearns: Proposed resolution is that if an element if fragmented into more than one element, it does not participate in View Transitions

RESOLUTION: if an element if fragmented into more than one element, it does not participate in View Transitions (plus note that we want to do such things in the future)

<khush> Next one is easier... I hope. :P

github-bot, take up w3c/csswg-drafts#8548

[css-view-transitions-1] Define the constraints which must be satisfied by a named element during the transition

<github-bot> OK, I'll post this discussion to https://github.com/w3c/csswg-drafts/issues/8548.

<JakeA> A view-transition-name value that isn't none gives an element stacking context, grouping element, backdrop root, similar to non-1 opacity, as view transitions need these constraints.

JakeA: If you give an element a transition name that isn’t none, it acts as if opacity is not 1
… Name is only checked during transition, but because the new view is live, we need to check constraints per frame
… If constraints are not satisfied mid-transition, element is dropped from the rest of the transition
… If an element isn’t rendered during setup, it’s ignored
… If an element becomes fragmented during transition, it’s dropped
… How do we check these conditions?
… Option 1: we assert extra conditions, then check to see if the view transition name is not none
… If a name ever becomes none, element is dropped

Option 2: We assert these all individually, regardless of name

flackr: Option 3, if an element is undergoing view transition, it is subject to the constraints

<khush> I'd be ok with that.

JakeA: We can’t enforce rendering and we wouldn’t enforce fragmenting

<vmpstr> +1

flackr: Right, we could continue to enforce name-based constraints

TabAtkins: My preference as well

fantasai: That makes sense; other thought I had was if the name changes at all, I wouldn’t be surprised if the transition is suddenly dropped

JakeA: We avoided that because it means we can’t deal with elements that suddenly gain a transition name

fantasai: I’m not saying you’d start a new transition, I’m saying if someone messes with names, it should be dropped

JakeA: If a paragraph isn’t in a transition and halfway through JS gives it a name, should it be ignored?
… If we deal with every element changed names, then you have to check every frame

astearns: It sounds like Option 2, except names are kept throughout the transition and so need to be checked?

JakeA: I think people like flackr’s option
… I’m happy with that

<khush> +1

fantasai: Wouldn’t you also be enforcing that it’s not fragmented?

JakeA: We would skip the transition in that case

fantasai: What if a thing becomes fragmented partway through? Would you just ignore that?

JakeA: The new views are live and updated per frame
… If an element becomes not-renderable…

fantasai: I get it

astearns: Option3

<JakeA> If an element is involved in a transition, the ``view-transition-name` constraints are enforced during the transition

<JakeA> It's skipped if other constraints are broken

<JakeA> (eg rendering and now fragmenting)

RESOLUTION: If an element is involved in a transition, the `view-transition-name` constraints are enforced during the transition

RESOLUTION: Conditions are checked per-frame; transition is skipped if other constraints are broken

github-bot, take up w3c/csswg-drafts#8278

[css-view-transitions-1] UA CSS should size ::view-transition to 0x0

<github-bot> OK, I'll post this discussion to https://github.com/w3c/csswg-drafts/issues/8278.

<JakeA> w3c/csswg-drafts#8278 (comment)

JakeA: Trying to decide default styles for the main pseudo-element
… It currently fills the snapshot root
… Use case one: rootless transitions
… By default we giive a name of root, but authors could change it to none
… Now when the transition runs, only components will be involved, but you can see the document beneath
… This is like a scoped transition, but it’s not quite a scoped transition
… I feel like this is rare and it will be more rare when we ship scoped transitions

Use case two: animating a view transition container and expecting it to move everything inside

Use case three: If you move your root view away, you might want to create a background for the rest of the area

Use case four: transitioning relative to the viewport
… We always go from top left, but in custom cases you might do something different
… I’ve done transitions to the center or bottom of the viewport
… So, the question is, what styles to give this by default.
… Option 1. It fills the viewport, which is great in all but the rootless use case
… Option 2. we do pointer-event: none to the transition and p-e: auto to the parts of the transition, so you can click the real DOM
… This is great except in cases where you fill in an opaque background; clicks will go through it
… Option 3: Make the transition element 0x0 in the top left, which breaks the ability to fill in the background
… Also break cases where you’re trying to position relative to places other than top left
… This feels like making the common things hard
… I think we’re in favor of option 1

TabAtkins: I agree, I think option 1 is the right idea and is least restrictive, also fails in a way that’s safer than the other options

flackr: I’m good with 1 or 3; 2 could override authors setting pointer-event on child elements
… We should add as few enforced UA styles as possible

fantasai: Conclusion seems fine; have slight concern that positioning default is top left, rather than being writing-mode dependent

khush: That’s correct, spec says to place but doesn’t say how to compute

JakeA: I understand the writing mode concerns, but this should result in the same effect in the default case

fantasai: Should look into whether there are things that compute differently

astearns: We should have a separate issue about writing mode being considered

khush: We did have that, but then made it relative to the center of the containing block
… I’ll reopen that issue so we can get things into the spec

astearns: Sounds like we’re converging on option 1

<khush> +1 to this proposal

RESOLUTION: The view transition fills the viewport and captures clicks

github-bot, take up w3c/csswg-drafts#7797

[css-view-transitions-1] User input should be ignored when rendering is suppressed.

<github-bot> OK, I'll post this discussion to https://github.com/w3c/csswg-drafts/issues/7797.

<JakeA> w3c/csswg-drafts#7797 (comment)

<khush> Jake's getting 'em all! :)

JakeA: During a transition, elements involved are hidden from the DOM
… That usually means every element is hidden, because the root element has a transition name
… Clicks during a transition will almost always hit the pseudo and fall to the document root
… Authors could change this by changing the root’s transition name to none
… Question is: what do we do with clicks while promises haven’t settled and the transition is frozen?
… Similar case: if you block the event loop using a while loop, it will block rendering
… If a user clicks anywhere, those events are queueing up
… Once the freeze is thawed, the events and hit tests and such are resolved then, which may resolve hits against things that moved
… We can’t do a full event block, but we could take from tasksources and then resolve when the transition starts
… Deadlocks are still possible in this option, which may also conflict with scoped transitions
… We don’t want to block all input events while scoped transition is happening
… Option 2: we apply all events to the document element
… In that case, a click may hit the document element whereas if we’d queued it, it might have hit a more specific element

<khush> +1 for option 2.

Rossen: I want to make sure we’re sticking to CSS

TabAtkins: +1 for option 2, which seems a little safer; also I hate when things resolve against DOM I wasn’t expecting; also makes things more predictable

flackr: I think a common case is that by the time you’d dispatch the events in option 1, the elements will be where they should be
… Worried that we’re seen cases transitions to move small pieces of sub-documents
… I strongly prefer option 1

khush: If we decide to buffer until rendering is done, the first question is do we dispatch before or after creating the pseudo-DOM?
… Why not just give it to the document?

JakeA: I think flackr’s point is that if you have a pseudo-element is in a certain place, option 2 raises the chances of a thing not being where it was when the click was made

khush: So this is for the case of rootless transitions?

JakeA: This is all about rootless transitions

flackr: If I start a transition on mousedown, as long as my pseudo is pointer-events: none, I can still get that click
… I also feel like you have a halting issue regardless, since there’s no requirement a transition ever finish

JakeA: Should have clarified that this deadlocks are already limited to four seconds

flackr: So this isn’t new, it’s just we could make them more likely
… If a developer doesn’t finish setting up for a view transition, there will be problems

chrishtr: With option 2, if the dev starts a transition but then does nothing and we wait four seconds, if the user clicks in that 4s window, is the click lost?

JakeA: Yeah, in option 2, the click won’t work

chrishtr: So the default UA behaviors are suppressed

flackr: In option 1, we wait for the transition to fail to start, the events are processed after the transition is canceled

chrishtr: Could we do an option 3 where user events are still processed and applied to the original target?

khush: Option 1 is very hard to reason about with scoped transitions, whichis why I’m advocating option 2
… The easiest thing is to dispatch an event at the root of the subtree,

<vmpstr> +1

flackr: An event targeted at the document provdes XY coords, yes?

khush: Yes

Rossen: We seem to be sliding to option 2; flackr, you were the main proponent of 1

flackr: I like that option 2 supports scoped transitions better
… I think it’s okay

Rossen: Any other opinions or objections to resolved on option 2?

(silence)

<JakeA> Target pointer events to the document element

<JakeA> This is what will happen during the transition in most cases anyway, except in the edge case mentioned above, where the root's view-transition-name is set to none, and the clicks don't hit the pseudos. In that case, click may hit the document element, where they would hit a more specific element during the transition.

RESOLUTION: target pointer events to the document element

<flackr> Or to the root of the transition for future compat with scoped transitions!

[css-view-transitions-1] Define behaviour when capturing image for a large element.

github-bot, take up w3c/csswg-drafts#8561

<github-bot> emeyer, ignoring request to take up w3c/csswg-drafts#8561 which is already the current github URL

JakeA: When we capture the content of an old view, we don’t know how it might be animated yet
… Part of the element might be out of view, and could come in view as part of the transition
… Some elements are very large and we can’t feasibly capture all of it
… Image transitioning the body element
… Proposal is, we’ll base the dimensions of the transition group on the element, but say that browsers don’t have to capture every pixel, while suggesting they capture beyond the viewport
… If possible/performant to do so
… Are we okay to handwave like that, so we let UAs act as they see best?
… Further, what should the natural width and height of the in- and out-states be when a browser chooses not to capture every pixels?
… Also, should those things be script-visible?

TabAtkins: I think we should require at least the visible area and some amount outside is good, maybe with a minimum explicit margin like 50% beyond
… We should expose the size of the thing being captured

fantasai: +1 to Tab, plus the size should be the size it actually is, even if there isn’t painting inside the entire range

<flackr> +1

fantasai: We should require or very strongly recommend capturing beyond the viewport as well, probably +1 viewport in each direction as the minimum range to capture

JakeA: So if there’s a case with many elements layered on top of each other, they’re all in the viewport; if device can’t handle all that, should we just skip the transition?
… I think that’s a good general case, that if a UA doesn’t feel it can handle a given transition, it should skip the transition

khush: +1 to fantasai, which is kind of what I was implementing anyway, so I’m okay with the spec recommending taking the root as a barometer for how much to expand beyond the visible viewport
… The spec says the natural size of the image is equal to what you capture and everything around it is transparent
… object view box exposes how much the UA decided to paint

fantasai: I don’t think you should use object view box to set this, even if you use the same computation internally

khush: So the computed value is meant to be ink-overflow-rectangle

chrishtr: We would just not raster things we can’t put into memory, so developers can’t observe anything about this behavior

fantasai: Exactly

<flackr> +1

JakeA: We can say the exposed value doesn’t say anything about optimizations

vmpstr: I think the object view box is the problem, because we need to make it the same as ink overflow, but if that’s infinite\

flackr: It’s the same as if you hadn’t rendered everything

khush: In the spec it says to paint everything in the ink overflow rectangle
… We pretend an image is the size of the ink overflow rect

chrishtr: A dev wouldn’t know whether we painted the whole thing or not, only the user can tell

khush: Base case where the UA can raster the whole thing, and element has drop shadow, so ink overflow is bigger than object box
… UA should compute a view box it applies to the element such that when you render this, the boxes should coincide at the same origin
… If the UA hasn’t painted the whole thing, and the dev msses with the object view box, the effect is the same as if the whole thing was painted
… My question is, to implement this, can we not let devs change object view box?
… When they read it, we can give the the value the spec wants; also the device specs wouldn’t be exposed?

fantasai: What is the ink overflow rectangle of something that has a box shadow?

chrishtr: There’s spec language about this

fantasai: Do we want to expose this?

khush: You could call getcomputedstyle and don’t see anything, which would make implementation easier

fantasai: That seems better, and if the dev wants to manipulate they don’t have to know about the internals

chrishtr: We could take this and whether we should add a new !important to a new rule

fantasai: I think we agree the rasterization is not exposed to devs but the returned values are spec-consistent

<fantasai> proposal: UA can limit rasterization for perf limitations, but must size the element as if it was fully rasterized

chrishtr: Agreed

JakeA: I think we generally agreed the spec should suggest an overflow amount, was it one viewport in each direction?

<fantasai> proposal: rasterization should cover at least the visible area of the viewport + one viewport in each direction

JakeA: Also in out-of-memory cases the transition is skipped

<fantasai> proposal: if the UA cannot performantly perform the view transition (for any reason) it must skip the transition

TabAtkins: We don’t usually specify memory problem recovery because it can show up whenever

fantasai: I think we have three proposed resolutions
… One (see above)

<TabAtkins> Exception is if OOM actually causes a security issue. In all other cases OOM behavior is explicitly undefined.

fantasai: Two look one viewport in each direction for overflow handling
… Three is the error fallback is to skip the transition
… And that you never do half a transition, you either do all or none

khush: One viewport in each direction should be a recommendation rather than a requirement
… Only requirement is that what’s visible must be captured

<fantasai> proposal: UA can limit rasterization for perf limitations, but must size the element as if it was fully rasterized

<fantasai> proposal: if the UA cannot performantly perform the view transition (for any reason) it must skip the transition

<fantasai> proposal: rasterization should cover at least the visible area of the viewport + one viewport in each direction

RESOLUTION: user agent can limit rasterization for performance limitations, but must size the element as if it was fully rasterized

<JakeA> proposal: Must: rasterization should cover at least the visible area of the viewport Should: + one viewport in each direction

<JakeA> proposal: Must: rasterization should cover at least the visible area of the viewport

<flackr> must + should = ?

<JakeA> proposal: Must: rasterization covers at least the visible area of the viewport

RESOLUTION: rasterization must cover at least the visible area of the viewport

JakeA: We need to consider the directions and how much overflow SHOULD be captured async

<bkardell_> I think no

flackr: Skipping the transition is dev-visible so we’re exposing device capabilities

fantasai: You can limit rasterization but if you’re getting to the point you can’t even transition what’s on-screen, you should skip the whole thing

flackr: We could not paint the transition but still run it so the dev knows it happened

bkardell_: You’re saying skipping the transition is dev-visible but is it? Because a device can just not support that or animations can be turned off with prefers-reduced-motion

Jake: We’ve decided those can be exposed, but giving away GPU memory is a fingerprint

bkardell_: So, are saying you could do something like try a _small_ transition and then kind of scale them up until it fails and then fingerprint with that? I see.

khush: Is it safer to say that this should silently fail by not painting things?
… We can already hit this with filters and blurs and such and that’s silent in Chrome

JakeA: I think we have to go back and come up with a plan here

Rossen: So we’ll have to postpone this resolution

end_of_meeting

Summary of resolutions

  1. if an element if fragmented into more than one element, it does not participate in View Transitions (plus note that we want to do such things in the future)
  2. If an element is involved in a transition, the `view-transition-name` constraints are enforced during the transition
  3. Conditions are checked per-frame; transition is skipped if other constraints are broken
  4. The view transition fills the viewport and captures clicks
  5. target pointer events to the document element
  6. user agent can limit rasterization for performance limitations, but must size the element as if it was fully rasterized
  7. rasterization must cover at least the visible area of the viewport
Minutes manually created (not a transcript), formatted by scribe.perl version 210 (Wed Jan 11 19:21:32 2023 UTC).

Diagnostics

Succeeded: s/directly/directly, until we have fragment pseudos (which we have talked about)/

Succeeded: s/Topic:/Subtopic:/

Succeeded: s/Topic:/Subtopic:/

Succeeded: i/Subtopic: [css-view-transitions-1] Capturing/Topic: View Transitions

Succeeded: s/Topic/Subtopic/

Succeeded: s/compete/compute/

Succeeded: s/Topic/Subtopic/

Succeeded: s/topic: break//

Succeeded: s/as well/as well, probably +1 viewport in each direction as the minimum range to capture/

Succeeded: s/I see/So, are saying you could do something like try a _small_ transition and then kind of scale them up until it fails and then fingerprint with that? I see.

Maybe present: ???, astearns, florian, Jake, khush, Rossen, TabAtkins

All speakers: ???, astearns, bkardell_, chrishtr, dbaron, fantasai, flackr, florian, Jake, JakeA, jensimmons, khush, Rossen, TabAtkins, vmpstr

Active on IRC: astearns, bkardell_, castastrophe, chris, chrishtr, dbaron, dholbert, emeyer, emilio, fantasai, flackr, florian, futhark, github-bot, JakeA, jensimmons, jfkthame, khush, lea, masonf, PaulG, Rossen_, TabAtkins, vmpstr