W3C home > Mailing lists > Public > public-fx@w3.org > July to September 2016

Re: [css-transforms] Unify the definition of transform-style & 3D context

From: Tien-Ren Chen <trchen@chromium.org>
Date: Mon, 26 Sep 2016 17:12:54 -0700
Message-ID: <CAKxkHO8sr0a3xGN_qFxK3V5d2pQ4UvD4yczqASPnu3pd6c-Mdg@mail.gmail.com>
To: Matt Woodrow <mwoodrow@mozilla.com>
Cc: public-fx@w3.org, Simon Fraser <simon.fraser@apple.com>, "Tab Atkins Jr." <jackalmage@gmail.com>, Rik Cabanier <cabanier@gmail.com>
On Mon, Sep 26, 2016 at 4:50 PM, Matt Woodrow <mwoodrow@mozilla.com> wrote:
> On 27/09/16 12:22 PM, Tien-Ren Chen wrote:
>> As I summed up in row 2~4 of my comparison sheet
>> (https://goo.gl/5dgFza), Chromium, Firefox, and Safari stack the
>> layers all differently (RGB, RBG, BRG, respectively) because they
>> create 3D context differently. An oversimplified explanation is that
>> Chromium followed the TR spec, Safari followed the ED spec, while
>> Firefox stuck somewhere in between (but closer to TR in general).
> Firefox is meant to the follow the TR spec. It looks like we have a bug
> where we combine sibling preserve-3d contexts for sorting and we shouldn't.
>> I studied many of the unspecified corner cases as I worked on
>> Chromium's clean-room compositing implementation (a.k.a. SPv2), I feel
>> strongly that the ED's definition is a no-go, because it introduced
>> the "3D context penetration issue". For example, "6.1.4. Accumulated
>> 3D Transformation Matrix Computation"(https://goo.gl/oKQpm2) is
>> ill-defined if the 3D-context-establishing element is not a containing
>> block.
>> In my opinion TR's definition is way more self-consistent, although it
>> does need some clarification. I would rephrase it this way:
>> transform-style is only applicable to elements that creates a stacking
>> context (i.e. with non-auto used z-index), as it modifies stacking
>> context behavior. The default value is 'flat'. A computed value of
>> 'preserve-3d' forces stacking context, and establishes containing
>> block for all descendants.
>> A stacking context with transform-style:flat works like a traditional
>> stacking context, sorting its child stacking contexts by their
>> z-index. If a child stacking context has 3D transform, the depth
>> component resulting from the transform is unused.
>> A stacking context with transform-style:preserve-3d propagates up
>> descendant planes created by 3D transforms if the parent stacking
>> context also has transform-style:preserve-3d. If its parent stacking
>> context has transform-style:flat, the inherited screen-space matrix
>> gets flattened. The collection of planes are sorted by depth and
>> composited with src-over.
>> To summarize, we have the following cases for an element:
>> A. z-index:auto && position:static : Normal flow
>> B. z-index:auto && !position:static : Pseudo stacking context
>> C. !z-index:auto && transform-style:flat && !3D-transformed:
>> Traditional stacking context, sorted child stacking contexts by
>> z-index.
>> D. transform-style:preserve-3d && parentSC.transform-style:flat :
>> Establishes 3D context. The flattened result sort with sibling
>> stacking contexts by its z-index. Establishes a default plane and root
>> stacking context for that plane.
>> E. transform-style:preserve-3d &&
>> parentSC.transform-style:preserve-3d: Inherit 3D context
>> Also if an element has 3D transform [#1] and it's parent stacking
>> context has transform-style:preserve-3d, its stacking context subtree
>> gets popped into a plane thus are not sorted against other sibling
>> stacking contexts. Its z-index is unused except for tie-breaking.
>> Note [#1]: A transform is 3D if and only if it contains any 3D
>> operation, even if if the computed local matrix has no depth
>> component. For example translateZ(0) is considered 3D.
> Why does C need to be !3D-transformed? I don't think the transform on the
> element with transform-style:flat changes the rendering of its children.

My bad. I meant to explain in a separate case that when with 3D
transform presents, transform-style:flat, and
parentSC.transform-style:flat, the whole thing still behave like a
traditional stacking context, and the depth component of the transform
is ignored.

> I also don't think we need to have the 2D/3D distinction in the spec. If the
> leaf element has a 2D transform and its parent stacking context has
> transform-style:preserve-3d, then we still want it to take part in depth
> sorting.

I'm particularly worrying about this case:

<style> div { transform-style: preserve-3d; } </style>
    <div style="transform:translateZ(0);">B</div>
    <div style="position:relative; z-index:0;">C</div>

If we don't make the distinction between 2D/3D (i.e. no plane / new
plane), the transition between translateZ(-epsilon), translateZ(0),
and translateZ(epsilon) could be tricky. IMO B should be popped into
its own plane, and perform depth-sorting against plane AC as a whole.

Another weird case:

<style> div { transform-style: preserve-3d; } </style>
<div id="A" style="background:some_image; translateZ(0);">
    <div id="B" style="transform:translateZ(0); position:relative;
z-index:-1;">Stuck in middle?</div>

Should B to stack in between the background/foreground of A because it
has negative z-index? I think the sensible thing to do is to pop it to
its own plane.

> - Matt
Received on Tuesday, 27 September 2016 00:13:30 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 19:49:57 UTC