-
Notifications
You must be signed in to change notification settings - Fork 711
[css-transforms-2] Preserve-3d + backface visibility semantics need to be clarified #918
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
The CSS Working Group just discussed
The full IRC log of that discussion<heycam> Topic: backface visibility<astearns> github: https://github.com//issues/918 <heycam> mattwoodrow: current spec says that backface-visibility only applies to the element it's on, not descendants <heycam> ... doesn't say it would create any plane or layer, which Gecko faithfully implements <heycam> ... other engines create a plane for all descendants but not positioned descendants <heycam> ... which is not something there's any precedent for, seems a bit crazy. would prefer backface-visibility create a stacking context <heycam> smfr: I think in WebKit it does create a stacking context, not a containing block <heycam> mattwoodrow: maybe it is that it doesn't create a containing block <heycam> chrishtr: definitely doesn't create a stacking context <heycam> smfr: I'd be scared to change hte behavior of backface-visibility... <heycam> mattwoodrow: so try to find a descroption of what it actually does. affects itself and non-positioned descendants? <heycam> chrishtr: self painting layers reset the backface visibility thing <heycam> mattwoodrow: don't know how to describe it for the spec <heycam> chrishtr: similar to the set of things dbaron found that caused "painting as if positioned" <heycam> ... in CSS 2.1, positioned elts paint later than regular elements <dbaron> https://dbaron.org/css/test/2018/stacking-context-z-order <heycam> ... anything that has an effect-y thing on it <heycam> ... this is exactly what is on self painting layers <heycam> ... so we could define it that way <heycam> florian: where else did we run into this? <heycam> chrishtr: might have been another case yes <heycam> ... but the thing about hte paint order is one that's not specified properly, is that right? <heycam> mattwoodrow: most of hte psecs that create stacking ocntext say that. but they mean create a stacking ocntext and sort it with positioned descendants <heycam> chrishtr: overflow:hidden, backface-visibility, SVG elements and other atomically replaced elements, ... <heycam> ... CSS clip probably <heycam> ... and the rest of them do create stacking contexts <heycam> ... we should define this, get interop on the table in dbaron's test, then use it for the backface-visibility definition <heycam> dbaron: I don't think there's a whole lot in there that's not creating a stacking context <heycam> ... CSS clip only applies to things that are positioned <heycam> chrishtr: but in terms of the "painting as if positioned" <heycam> ... I think overflow:clip is the most common <heycam> dbaron: have we added that yet? <heycam> chrishtr: I mean overlfow:hidden and scroll <heycam> ... on the issue in which this table resides, I mention there's a silly quirk in Chrome and probably WebKit, not triggering self painting in some bizarre corner cases of scrolling <heycam> smfr: WK does not create self painting layers for [...] <heycam> dbaron: I don't htink Gecko sorts overflow:hidden on to positioned descendants list <heycam> mattwoodrow: don't think so <astearns> s/[...]/overflow:hidden/ <heycam> mattwoodrow: overflow:hidden isn't a stacking context, can interleave things inside and outside, so can't go in the positioned descendants list <heycam> smfr: so is everything on the list make stacking context? <heycam> mattwoodrow: yes <heycam> chrishtr: overflow:hidden does not create a self painting layer (in Blink) <heycam> ... if there's overlfow:scroll but is in effect like overflow:hidden since there's nothing to scroll, then we skip it <heycam> ... that's something we could change in Chrome <heycam> ... in any case, is this a good way to spec it? <heycam> mattwoodrow: yes, I agree the CSS 2.1 spec describes floats [...] <dbaron> I think Gecko calls this "pseudo-stacking context" <heycam> RESOLUTION: Add a new "pseudo-stacking context" definition and use it to define how backface-visibility works <heycam> dbaron: some of this would be easier if there's a spec to put this old CSS 2.1 text to evolve it <heycam> ... maybe a central painting spec <heycam> -- break until 4pm -- <TabAtkins> ScribeNick: TabAtkins |
Until we have a new spec, css-transforms-2 should more clearly specify backface-visibility:hidden. Matt, would you like to take a stab at this? |
There are two aspects to this issue: preserve-3d and backface-visibility. For backface-visibility, there was a resolution earlier this week that |
For preserve-3d: we could use the same concept. The current Gecko semantics are that the DOM ancestor of an element flattens if it does not have Proposal which relaxes the above a bit: only elements that induce pseudo stacking contexts can cause flattening. Thus this example would preserve 3d across the
But not:
This will probably improve interop, makes it a bit easier to structure content in some cases, and may be more consistent to reason about if we do the same thing for |
Now for perspective CSS: Blink and WebKit both use the enclosing stacking context ancestor that is composited. Therefore, behavior is a side-effect of compositing. :( If an element has a 3D transform, then its nearest DOM ancestor with perspective is also composited (and because it has perspective it is also a stacking context). However, there may be an intermediate stacking ancestor that is below the perspective and above the transformed element. Example 1 (perspective is applied to
Example 2 (no perspective applied in Blink (still does in WebKit, not sure why), only because of compositing.
|
Blink should be able to change behavior to not depend on compositing any more for perspective, along with a corresponding change to preserve-3d. |
My understanding of the resolution was that backface-visibility:hidden would establish a pseudo-stacking context, such that the backface of the element and all descendants would be hidden, excluding descendants that are positioned or establish stacking contexts (full only, not pseudo). |
In my mental model, I consider an element with transform-style:preserve-3d, and a parent without (or with a flattening property) to create a 3d rendering context (rather than extend the parent's one). The flattening happens at the root of the 3d rendering context, so the element with preserve-3d is the one outputting a flat representation. The subtle difference here is that it's clearer that two siblings with transform-style:preserve-3d and a transform-style:flat parent do not intersect with each other, since they're each create a separate 3d rendering context. If we consider the parent to be the one that flattens, then it's harder to explain why the two preserve-3d children don't intersect.
Given the above, I think the required spec text to explain how to differentiate between transform:style:preserve-3d creating or extending a 3d rendering context is complex. You have to walk the DOM tree (not containing block chain), looking for the first pseudo-stacking context, and check if that also has transform-style:preserve-3d. But, you also have to check the intermediate elements for a flattening property (like overflow:hidden), which does break the preserve-3d, but isn't a pseudo-stacking context. For that reason, I'd much prefer to trial using the direct parent to check for preserve-3d, just since it's much simpler to explain and understand. |
For perspective, I think we could say the nearest (pseudo-)stacking context ancestor, since we don't need/want flattening properties in the middle to break it (and we're explicitly relying on that for the parallax scrolling effects). I had a chat to @smfr on Friday, and we'd both still prefer to say the DOM parent though, since it's Would you be ok with trialing this behaviour, and we can reconsider the approach if there's serious webcompat breakage? |
Sure, but this is the same as what I said, no? The descendants that are positioned or establish stacking contexts is nearly the same as pseudo stacking context. |
Oh right. I had forgotten about the conflict of overflow:hidden not inducing a pseudo stacking context, yet still flattening. This is a good argument in favor of the DOM parent approach.
Yes! For sure I'm ok with trialing this behavior. I want clear and simple semantics also. :) I only suggested the loosening because when I wrote it it seemed simple (and I forgot about overflow:hidden, as noted above). But I think it's not, because of the reasons you outlined. |
Could you clarify what you meant by "explicitly relying on that"? Do you mean we're relying on support for intermediate non-stacking context elements between the perspective and transformed elements? @flackr for input also.
I agree it's simpler and consistent.
Need to check parallax use-cases first.. |
Yes will trial it (discussed offline with @flackr) |
Rather than specifying the 'pseudo stacking context' concept as discussed earlier, I'd like to suggest a different approach:
For the majority of cases, this should be a no-op, as elements with For the small number of cases where an untransformed element has There's still some complexity, in that the backface that is hidden is a plane containing the element and all descendants, with the exception of children that are participating in the 3d rendering context themselves. I think that's an existing problem with the spec though, that the concept of what exactly planes get formed is still undefined. |
I think this seems like a good approach. A few comments:
We probably need to do some measurement/testing of whether we're going to have any compatibility problems with this approach, but it seems like a sensible plan and one that has a reasonable chance of being sufficiently compatible. |
@mattwoodrow I like this approach, thanks for driving it! |
I think that's fine, but
Also agreed! I think we need to define this as part of
Does that mean for this example:
We'd see just the red colour? I guess that means that the green element doesn't really participate in the 3D rendering context.
Fingers crossed it works out! I'll aim to implement the current plan in WebKit, behind a testable flag and can go from there. |
…context and containing block when participating in a 3D rendering context. (w3c#918)
The discussion in #3305 was relatively unfavorable to making distinctions based on syntactic 3D-ness, and the spec currently disallows it for the individual transform properties, although not for |
I feel like that case is somewhat different (in my mind, at least), in that UAs were using the presence of a 3d transform function as an internal heuristic for which rendering path to use (which also had very subtle rendering differences due to antialiasing), and there was resistance to leaking that into the spec since it should just be an implementation detail. In this case, the 3d-ness is super relevant to what we're trying to define, so I think it's more reasonable to put into the spec. I agree that using the 3D functions rather than the computed matrix has more predictable behaviour. Regardless, this might be worth putting on the Agenda to discuss more widely. |
Based on https://bugs.chromium.org/p/chromium/issues/detail?id=954591#c21 I think we may also need to include having |
Should this all be described as part of the 3D transform rendering model? The current description is that 'An element participates in a 3D rendering context if its parent establishes or extends a 3D rendering context.' Should that be somewhat changed to describe the various planes that are created? I think we're suggesting that all elements that create or extend a 3D rendering context get a plane, as do elements that have a 3d transforms and have a parent that creates or extends a 3D rendering context. Everything else is included in the plane of the rendering context (as normal for stacking contexts). |
I should think about your most recent comment -- but before I forget I want to add a clarification to #918 (comment) . It's actually a little more complicated because I think the additional condition for applying an element's own |
Can you explain a bit more about why we need that restriction? If we said that an element with a 2d transform (and a |
I think the concern was that in this testcase the green rectangle is interoperably shown and we were hesitant to change that, at least in the same change that's needed to fix the Interop2023 failure. (That said, in Chrome it's shown because of the |
I don't see the green div in Safari if I drop the Should |
Should this be unconditional? Otherwise, changing |
(cc @tnikkel as well) |
The CSS Working Group just discussed The full IRC log of that discussion<fantasai> dbaron: Not looking for a decision, wanted to summarize what's going on to make sure people are aware.<fantasai> dbaron: The underlying issue in this old issue is that we have backface-visibility <fantasai> dbaron: which hides things when facing backwards in 3D rotation <fantasai> dbaron: but we don't have a good definition of what this means <fantasai> dbaron: fundamental thing we're missing is "what is *this* that you are hiding" and "which descendants do you consider" <fantasai> dbaron: Discussed with Matt Woodrow, basic proposal in the issue <fantasai> dbaron: Matt wants to try prototyping, hopefully it won't break the world <fantasai> dbaron: and if it works, we'd like to specify backface visibility this way <fantasai> dbaron: it will require changes to all implementations <fantasai> dbaron: These are things that are not particularly interoperable, or particularly sensible. <TabAtkins> (I think this is the proposal (+ some clarifying comments in following comments) https://github.com//issues/918#issuecomment-1696711327) <fantasai> dbaron: if you care about this feature, pay attention to this <fantasai> dbaron: Beyond that, if people would like a summary I can try <fantasai> dbaron: but gets very technical very quickly <fantasai> Rossen_: Do we have the right people? <fantasai> dbaron: Don't know person from Gecko <fantasai> dholbert: Timothy Nickel, probably <dholbert> s/Nickel/Nikkel/ <fantasai> dbaron: The two people both involved are both former Gecko now involved in other engines (Blink, WebKit) :) <fantasai> dbaron: when you set backface-visibility: hidden, one question is which descendants do you apply to and which not <fantasai> dbaron: we don't want to apply to a descendant that itself has a 3D transform <fantasai> dbaron: because it might be rotated more and be visible. So it should be independent <fantasai> dbaron: For starters, this probably is required by Web-compat; but probably also sensible behavior <fantasai> dbaron: My suggestion was that we distinguish based on syntax of tranform <fantasai> dbaron: i.e. whether you are 3D is based on whether you write translate() or translate3D() <fantasai> dbaron: we got rid of such distinctions in the past, but I think it's the right thing to do here <fantasai> dbaron: 1. [missed] <fantasai> dbaron: 2. Can avoid discontinuity at animations <fantasai> dbaron: you don't want backface-visibility participation to pop during the animation <emilio> q+ <fantasai> dbaron: 3. It gives authors an escape hatch. <fantasai> TabAtkins: TypedOM preserves that distinction for legacy reasons, but can continue to preserve <fantasai> emilio: interpolation as a matrix? <fantasai> dbaron: Your interpolation is either matrix() or matrix3D() <fantasai> emilio: if it's preserved in the computed value, then seems reasonable <fantasai> dbaron: Not ready to take a resolution yet <fantasai> emilio: When you have matched transform lists, basically coalesce into something that assumes 3D, idk if that's the case in Chromium or WebKit <fantasai> emilio: that may make this trigger unexpectedly <Rossen_> ack emilio <fantasai> dbaron: might need to audit some of those codepaths <fantasai> dbaron: we removed some distinctions, might need to revisit <fantasai> emilio: Part of the proposal makes backface-visibility be a CB for fixed descendants, but only in some cases? <fantasai> emilio: that seems a bit annoying <fantasai> emilio: changes to preserve3D ancestors could end up reparenting things in the box tree <fantasai> emilio: doable but not fun <fantasai> dbaron: We wrote it that way because strong suspicion it wouldn't be Web-compatible otherwise <fantasai> emilio: because of [missed] <fantasai> dbaron: Matt might remember more <fantasai> dbaron: If we want telecon time, should schedule a separate breakout time, because we don't overlap on the two regular call times |
One issue that came up in crbug.com/391504029 is whether It's not clear to me right now whether or not that makes sense. (I should probably try to think about it more when I have a chunk of time to load this stuff into my head again...) But I'd welcome opinions form others on this case. |
Specifically, an element creating a new 3d rendering context should not inherit parent backface-visibility. I'm not sure if this is correct in the spec's perspective, but it avoids a failure of DCHECK in cc which requires backface inheritance not to cross 3d rendering contexts. dbaron@chromium.org added a comment at w3c/csswg-drafts#918 (comment) so that we can think about it more in the future if we need to. Bug: 391504029 Change-Id: I1c4e2b45d0adb0dd116d96373114fde8a53fdb90 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6207584 Reviewed-by: David Baron <dbaron@chromium.org> Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org> Cr-Commit-Position: refs/heads/main@{#1413640}
If we're treating |
Yeah, inherited isn't really the right word (although we do use it in our compositor code, when indicating that one compositor layer should take its I'm mentioning it because I think in the discussion starting at #918 (comment) we hadn't listed forming a new 3D rendering context as one of the things that pops something out of the plane to which |
Ok, makes sense!
I don't think it should, because the root of a 3D rendering context flattens to 2D space and then it's just normal content within the scope of the outer plane/stacking context. The decisions about whether content should form a new plane only makes sense (I think) within the scope of a single 3D rendering context. |
Sorry, I missed this and doesn't look like it was fully captured in the meeting transcript. The concern was that authors have been using |
https://www.w3.org/Bugs/Public/show_bug.cgi?id=23015
The text was updated successfully, but these errors were encountered: