w3c / csswg-drafts

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

[css-view-transitions-1] Clarifications on stacking contexts #8917

Open fantasai opened 1 year ago

fantasai commented 1 year ago

https://drafts.csswg.org/css-view-transitions/#view-transition-stacking-layer

Its parent stacking context is the root stacking context.

“root stacking context” isn't a defined term in Appendix E. Did you mean “root element’s stacking context” or something else?

If the ::view-transition pseudo-element exists, a new stacking context is created for the document element and the document's top layer. The view-transition layer is a sibling of this stacking context.

It's not clear to me what structure you're creating here, is it

or

?

The view-transition layer paints after the stacking context for the document element and document's top layer. This includes the filters and effects that are applied to the document element.

Is this trying to say

?

khushalsagar commented 1 year ago

We took the term "root stacking context" from the fullscreen spec. I realize now that its not well defined in that spec either : https://drafts.csswg.org/css-position-4/#document-top-layer:~:text=Its%20parent%20stacking%20context%20is%20the%20root%20stacking%20context.

Not sure if that concept should go into the top layer spec or in Appendix E. Latter makes more sense, its supposed to elaborately define stacking contexts. :)

It's not clear to me what structure you're creating here

The second one:

Generally the stacking context for "document element and top layer stacking context" is the root of the stacking context tree but we create a new one during the transition. Since the root element's image comes from the root stacking context. Amongst other things, its related to the question below.

Is this trying to say

Option b, they apply to document element and top layer but not to view transition layer. We paint the stacking context for "document element and top layer" into a canvas to generate the image for the root element and then feed that image into the view-transition-old/new elements.

It's an existing pattern to lift some effects (background color and effects like filter/opacity) from the root element onto the canvas which paints both the root element + top layer elements. So we have to capture the painting of this stacking context to make sure the image for the "root" is correct. It can be a bit odd that view-transition-name is on the root element while in practice it takes the output of the stacking context which includes the root element + top layer stuff. But its building on the same pattern we do for these effects.

tabatkins commented 1 year ago

The concept belongs in Position 4, yeah. I just haven't yet taken the time to define the bits that View Transitions needs to rely on. (The VT layer, which is above the top layers, etc.)

fantasai commented 1 year ago

Merged in clarifications, leaving this issue open to track handling this comment from @khushalsagar:

One point which I want to make sure is obvious is that the root and top layer elements don't paint during the regular DOM if they're "captured in a view transition", a.k.a, computed value of view-transition-name on the root element is not none.

The spec text here is supposed to cover that: https://drafts.csswg.org/css-view-transitions-1/#setup-transition-pseudo-elements-algorithm:~:text=The%20new%20element,until%20new%20exists. If you have any better ideas to include that here (even in a normative note), would be good!

khushalsagar commented 11 months ago

I think the ambiguity here is related to how we describe painting of captured elements:

  1. The spec text here says that any element being captured in a transition will not paint or hit-test. The root element can also have this bit set.
  2. The spec text here says that when generating an image for the root, also include top layer elements.

Logically 1 would imply that only the root element is generating an invisible box. Top layer elements are being painted as usually. While all elements captured in an image would be generating invisible boxes.

https://github.com/w3c/csswg-drafts/pull/9159 should fix this.

mattwoodrow commented 3 months ago

It's an existing pattern to lift some effects (background color and effects like filter/opacity) from the root element onto the canvas which paints both the root element + top layer elements.

Is this pattern specified anywhere, apart from background (which is here)?

I had a quick play, and it seems very inconsistent between different effects (filter, opacity, backdrop-filter, mix-blend-mode, isolation etc) and different engine implementations.

khushalsagar commented 3 months ago

^ @chrishtr probably knows. IIRC he worked on the spec discussion + Blink implementation in this area.

chrishtr commented 3 months ago

^ @chrishtr probably knows. IIRC he worked on the spec discussion + Blink implementation in this area.

Example in a spec:

https://drafts.fxtf.org/compositing-1/#pagebackdrop https://drafts.fxtf.org/compositing-1/#rootgroup

Filters also have this behavior and I think it's in the spec by way of compositing-1. It was discussed at the CSSWG a few years ago.

Chromium should agree with the spec on these points and there are WPTs.

mattwoodrow commented 3 months ago

^ @chrishtr probably knows. IIRC he worked on the spec discussion + Blink implementation in this area.

Example in a spec:

https://drafts.fxtf.org/compositing-1/#pagebackdrop https://drafts.fxtf.org/compositing-1/#rootgroup

Doesn't that explicitly say that filters/opacity are not lifted up to apply to the canvas?

The 'Root Element Group' paints the background of the root element (which always has a used value of 'transparent'), and then applies any filters/opacity specified for the root element.

Then the 'Root Group' paints the canvas, which includes any background that was specified for the root element (or possibly the element). No filters or opacity get applied to this as far as I can see.

chrishtr commented 3 months ago

An example WPT test is here.

It tests that "a filter on the root element applies to its background" (which is why the background in this example should be white, not black). Since the background is lifted into the root group, the filters have to apply in that also. The root element group is above any group for the HTML element.

mattwoodrow commented 3 months ago

An example WPT test is here.

It tests that "a filter on the root element applies to its background" (which is why the background in this example should be white, not black).

The test makes sense, and I agree that it's probably the desired behaviour, I'm just struggling to understand how the current spec text defines it.

Since the background is lifted into the root group, the filters have to apply in that also.

The root group, or the root element group? My read is that it is indeed the root group, which is an ancestor of the root element group that paints the filter.

The root element group is above any group for the HTML element. The HTML element is frequently referred to as the root element, which may be causing confusion here.

The CSS backgrounds spec defines the term 'Canvas background' (which paints the propagated background from the <html> or <body>), and 'Canvas surface' (which paints the UA-defined, usually white, colour).

Is the intent the the 'Root Element Group' includes the 'Canvas background' (and the entire tree of the root element), whereas the 'Root Group' then includes the 'Canvas surface'?

chrishtr commented 3 months ago

The root group, or the root element group? My read is that it is indeed the root group, which is an ancestor of the root element group that paints the filter.

You're right that it's specified as the "root element group". (It's been a few years it's hard to keep all these subtleties in my head.)

But the root element is not the same as the HTML element. There is an element representing the document itself, which is the parent of the HTML and top layer elements. In Blink that's called the LayoutView. In WebKit I think it's called the Render view. That's the place to which the background, filter etc are lifted.

The root group, on the other hand, is a final step for compositing that makes sure pixels from web pages are not blending with OS colors (or at least that browsers generally don't do so). For iframes the root group is transparent because it blends with the parent document's colors.

I think I got it right this time... :)

mattwoodrow commented 3 months ago

But the root element is not the same as the HTML element. There is an element representing the document itself, which is the parent of the HTML and top layer elements. In Blink that's called the LayoutView. In WebKit I think it's called the Render view. That's the place to which the background, filter etc are lifted.

Alright, makes sense. I am in agreement with everything except naming.

I think 'element' would generally refer to the HTML/DOM Element class, and neither the document or the RenderView/LayoutView implement that.

The only existing spec concept (that I'm aware of) that describes this place to where the background is lifted is the canvas background.

I'll make a PR for compositing-1 to try clarify that the 'Root Element Group' definitely includes this.