Re: [css-transforms] CSS3D breaks with opacity flattening

Response below (looking for opinions from all).

*/#!/*JoePea

On Mon, Sep 26, 2016 at 5:53 PM, Tien-Ren Chen <trchen@chromium.org> wrote:

> My two cents is that the web spec should be like laws --- codify what
> people do and people expect in the real world. Therefore I personally
> support the proposal "when an element have both
> transform-style:preserve-3d and opacity other than 1, the opacity
> value applies to the stacking context subtree in the current plane,
> and also applies separately to each planes propagated from the
> descendants."
>
> However such proposal is ambiguous when other aspects of the spec is
> ambiguous. For example, the current spec doesn't define what makes a
> plane:
>
> <style> div { transform-style:preserve-3d; } </style>
> <div style="opacity:0.5;">
>     A
>     <div style="transform:translateZ(0);">B</div>
>     <div style="position:relative; z-index:0;">C</div>
> </div>
>
> Should be the stacking order equivalent to:
>
> <style> div { transform-style:preserve-3d; } </style>
> <div style="opacity:0.5;">
>     A
>     <div style="position:relative; z-index:0;">B</div>
>     <div style="position:relative; z-index:0;">C</div>
> </div>
>
> Because everything are co-planar, or:
>
> <style> div { transform-style:preserve-3d; } </style>
> <div style="opacity:0.5;">A</div>
> <div style="opacity:0.5; transform:translateZ(0);">B</div>
> <div style="opacity:0.5; position:relative; z-index:0">C</div>
>
> Because every child stacking context is considered an individual plane, or:
>
> <style> div { transform-style:preserve-3d; } </style>
> <div style="opacity:0.5;">
>     A
>     <div style="position:relative; z-index:0">C</div>
> </div>
> <div style="opacity:0.5; transform:translateZ(0);">B</div>
>
> Because C is considered on the same plane as A?
>
> I actually had a lengthy debate with Chris before we shipped the
> change, and I was convinced that the new spec will introduce least
> ambiguity understood by vendors and web developers (which is a very
> desirable property of a spec!).


​This is true!​ However flattening opacity is very undesired. The best
solution is to spec an alternative (if not legacy-like) behavior before
shipping these breaking changes (and you know it!).


> We are fully aware the spec change
> won't be backward compatible. However the fact that you complained
> about the spec change actually reinforced the confidence that we can
> get away with it, because that implies this area is still actively
> developed, the contents are alive, and the framework authors will
> adapt to the change. In other words, we favored simplicity


This also means you are also favoring what I believe to be wrong invalid
behavior when considering the effects from an outer API perspective. For
someone like me who doesn't always read specs (most people don't have to
because implementation detail often doesn't matter), for someone like me
who observes the behavior of the outer web API, this change is simply wrong
because *applying opacity should not suddenly move your object's vertices!*

I hope you can at least agree with me there.

I'd be interested to know if you know of any 3D game engine that does
opacity flattening on it's 3D objects.

Chrome 53 is following specs, which is a good thing in general, but in this
case the spec has a flaw. I want all browsers to follow specs, and I also
want the specs to be correct.

The behavior in Chrome 52 was more desirable.

*However! *Even the "legacy" behavior in Chrome 52 does not allow us to
apply opacity to a parent without affecting the opacity of the parent's
descendants. There is no way to do this in the "legacy" implementation *or*
in the new implementation.

For perspective, the behavior in Three.js scenes is this
<https://github.com/mrdoob/three.js/issues/9782>: opacity is applied to
materials, and a material can be applied onto content of a scene graph node
(Object3D) without the opacity affecting child nodes. Multiplication of
opacity down the graph would be up to the end user to implement manually.

Thinking along those same lines, and considering that in the "legacy"
behavior of Chrome 52 we can't opacify a parent without affecting children,
I believe a better solution to spec would be for opacity to apply to the
element's paint (it's plane) without flattening it's 3D children, and
without applying any opacity to the 3D children, where by "3D children" I
mean any content that has been popped out into a new plane within a 3D
context.

The rule can be somewhat along the following lines, and backwards
compatible with the 2D content of the web:


   - If transform-style is flat, which is the default for the 2D-based web,
   then opacity should be a grouping property and will multiply with children
   of the parent where opacity is applied and all the way down the tree. *This
   makes sense because the opacity is being applied to a single flat plane
   which can essentially be considered a plane in 3D space who's texture
   includes all of the flat content rendered onto it.*
   - If transform-style is preserve-3d, then opacity does not need to be
   strictly a grouping property (like Tab Atkins mentions multiple times as
   the reason that opacity must flatten). In this case, opacity can apply only
   to the plane that the opacity is applied to, and not any of the 3D children
   that have been popped out into their own new planes. In effect, opacity
   would be semi-grouping, and would only affect children that reside on the
   plane where opacity is applied. In this case Tien, it would be important
   for us to solve the stacking context problem
   <https://lists.w3.org/Archives/Public/public-fx/2016JulSep/0071.html> and
   it would make great sense that any element with `transform:translateZ(0)`
   should be popped into a new plane in the 3D context, otherwise the plane
   would momentarily have opacity in the transition from -epsilon to epsilon,
   and that just doesn't make sense. It should just be a separate 3D object
   along the continuous spectrum.

It would be really great for something like this to be spec'd for one
simple reason: it does not break the principles of CSS, because if someone
wants to propagate opacity down the 3D scene graph, *they can do
it without modifying the DOM structure (without modifying the HTML markup).*

The new behavior *breaks CSS principles* because the needed workaround
forces one to modify DOM structure (markup), in order to apply what should
only be visual styling.

Note, what I am proposing may also apply to any blending properties, not
just opacity; anything that interacts with backdrop. So flattening would
not need to occur all the time when 3D is involved. Flattening seems to
stem from Tab's constant reiteration that the properties are "grouping".
So, why don't we just make them non-grouping as far as
3D-elements-popped-out-into-their-own-plane go?

Additionally, I feel that it would be even better to give developers
control over the behavior: there could be a new CSS property called
something like `blend-3d` that would enable/disable arithmetic of blend
modes (opacity, etc, anything that interacts with a backdrop) down 3D
elements in a 3D context.

For example:

```css
div {
  blend-3d: auto; /* Defaults to "single" which does not multiply down 3D
descendant elements in a 3D context. */
}

div {
  blend-3d: single; /* does not multiply down 3D descendant elements in a
3D context. */
}

div {
  blend-3d: multiply; /* multiplies down 3D descendant elements in a 3D
context, and perhaps it stops at the next 3D descendant element that has
"blend-3d: single". */
}
```

where by "3D descendant elements" I mean any element that has been popped
into it's own plane.

What do you all think about something like this?


> and
> unambiguity over convenience on this decision.
>

Sure, the new spec is less ambiguous (just as unambiguous as saying
"convert anything with opacity into a circle"), but the new behavior is not
just slightly less convenient. IT IS A PAIN IN THE ASS.

If you've read about my case (I would be glad to share with you over a
video call if that helps), the new behavior will cause my library to get
more *complex and error prone*, consume *twice as much memory* in order to
render the proper non-nested DOM structure next to my nested custom-element
DOM structure, and the number-to-string-to-number conversion needed in
order to pass values to the CSS engine will go from constant (with a value
of 1) to N where N is the number of descendants inside the target element
where opacity is being applied which means another *huge CPU and Memory
cost*.

I'd love to skype with you to show you the problems.


>
> On Mon, Sep 26, 2016 at 5:06 PM, /#!/JoePea <trusktr@gmail.com> wrote:
> > If you guys are against opacity being applied to descendants of the
> targeted
> > element, then maybe, instead of flattening, the opacity should just
> apply to
> > the target element's own paint and those descendants that are popped out
> and
> > exist in the same 3D space would not be affected by the opacity. Opacity
> > multiplication would be up to the end developer, and I could live with
> that.
> >
> > But the current behavior is wrong from a 3D perspective. Opacity should
> not
> > suddenly and unexpectedly move all the vertices of a 3D object onto a
> common
> > plane.
> >
> > Please, let's revise the spec, no matter how hard that may be, and let's
> get
> > it right.
> >
> > - Joe
> >
> > /#!/JoePea
> >
> > On Fri, Sep 23, 2016 at 12:58 AM, Rik Cabanier <cabanier@gmail.com>
> wrote:
> >>
> >>
> >>
> >> On Fri, Sep 23, 2016 at 12:39 AM, Matt Woodrow <mwoodrow@mozilla.com>
> >> wrote:
> >>>
> >>>
> >>> On 22/09/16 11:37 PM, Rik Cabanier wrote:
> >>>
> >>>
> >>> In addition, your proposal *also* affects web content because opacity
> is
> >>> now applied to the group instead of being distributed to the children.
> >>>
> >>> It's true, but I figured it would be close enough to the old rendering
> >>> that the majority of existing content would work with it (assuming
> they just
> >>> want opacity, not specifically opacity distributed to the children)
> while
> >>> also being correct wrt group-opacity and not implementation dependent.
> >>>
> >>>
> >>>>
> >>>> This thread was started by an author who's content was broken, so it
> >>>> seems reasonable to re-visit these assumptions.
> >>>
> >>>
> >>> Yes, we went over his examples and told him how to fix it (= apply
> >>> opacity to the elements)
> >>> Since Firefox knows that it's flattening, could it create a warning in
> >>> the console and point to an MDN page with more information?
> >>>
> >>> 1:
> >>> https://groups.google.com/a/chromium.org/forum/#!msg/blink-d
> ev/eBIp90_il1o/jrxzMW_4BQAJ
> >>> 2: https://bugzilla.mozilla.org/show_bug.cgi?id=1250718
> >>> https://bugzilla.mozilla.org/show_bug.cgi?id=1278021
> >>> https://bugzilla.mozilla.org/show_bug.cgi?id=1229317
> >>>
> >>>
> >>> I still think that applying group-opacity to a subset of a 3d scene is
> a
> >>> reasonable use case (that can't be easily solved without this), and
> one that
> >>> we could support without breaking anything worse than we already plan
> to.
> >>>
> >>> Doesn't look like this is getting much traction though, so I'll
> probably
> >>> just accept the spec change and go ahead with ship flattening of
> opacity in
> >>> Firefox.
> >>
> >>
> >> Good to hear! This was a great discussion.
> >> If you (or anyone else) can come up with a better solution, maybe we can
> >> add it to the spec as another value when we integrate Simon Fraser's
> >> proposal.
> >
> >
>

Received on Tuesday, 27 September 2016 18:08:23 UTC