Open Bug 725299 Opened 11 years ago Updated 6 years ago

Wrong z-ordering with css 3d transforms using opacity and transform-style


(Core :: Layout, defect)

10 Branch
Not set





(Reporter: jl, Unassigned)



(1 file, 1 obsolete file)

Attached file preserve3d+opacity issue example (obsolete) —
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:10.0) Gecko/20100101 Firefox/10.0
Build ID: 20120129021758

Steps to reproduce:

In a simple web page (see attached example) using css tranforms to position 2 div elements in a 3D space: div1 and div2 with div1 "behind" div2 (i.e. with a lower Z).
The style of div2 contains an "opacity" property < 1 and a "transform-style: preserve-3d;" rule.
div1 and div2 have one or more child(ren) (one div in the attached example, but using an img cause the same behaviour).

Actual results:

div1 is displayed in overlay over div2

Expected results:

div1 should be displayed behind div2.

The issue seems to be related to the association of opacity and preserve-3d transform style in div2's style. In effect, in d2 style, when removing the opacity rule (or setting opacity to 1) or removing the transform-style rule, the z-ordering of div2 behind div1 is correctly managed.
Fixed mime-type of previous attachement (was text/plain, should be text/html)
Attachment #595399 - Attachment is obsolete: true
Attachment #595403 - Attachment mime type: text/plain → text/html
Component: Untriaged → Layout
Product: Firefox → Core
QA Contact: untriaged → layout
In CSS, opacity affects z-ordering.  Does the 3d transforms spec define the interaction between its z-ordering and opacity z-ordering?
The position on the Z axis of a transformed element does not affect the order within a stacking context. With elements at the same z-index, objects are drawn in order of increasing z position.

I interpret this as: if 2 sibling elements have the same z-index property and are transformed with a 3d-transform, the Z positions of the 3d-tranform is commands the z-ordering (and possible intersection) to those elements.
This also seems quite logical to me.

Do you agree?
> The position on the Z axis of a transformed element does not affect the order within a
> stacking context.

Ok, but within a stacking context things are sorted not merely by z-index.  They're also sorted based on whether they form stacking contexts, and setting 'opacity' to a value other than "1" creates a separate stacking context for the element.
In particular, see and

What the transform spec needs to do is precisely describe exactly how it modifies appendix E.  Right now it doesn't do that.  In particular, the two sentences you quoted are self-contradictory: the order within a stacking context depends on more than just z-index, so the first sentence says that z-position never changes painting order while the second one says that for the particular case of elements in at the same z-index (whatever that means in practice) it does...
I agree that the W3C 3d transform spec is rather ambiguous on this point...

However, from a CSS designer's point of view, it would be really weird and frustrating that 2 divs inside a same element with a 'preserve-3d' transform-style don't respect the 3D geometry as soon as you reduce the opacity of one of them!

Consider for example a keyframe animation for swapping 2 images and bringing one to the background of the other. The one  moving to the background could have its opacity animated as well to produce an effect of distance fading.
If the change in opacity make it move to the front, the benefit of 3d transform is totally lost!

Note: I can not reproduce similar types of artifacts with 3d transforms in webkit-based browsers (namely in Safari and Chrome). Chrome even tends to have an opposite - and annoying - behavior, ignoring z-index attributes when 2d transforms are done on elements (workaround is to add a TranslateZ(-1px) to enforce planes ordering...
We can fix this, by making WrapPreserve3DListInternal smarter --- moving all the children of nsDisplayOpacity up to replace the nsDisplayOpacity, and wrapping all the non-transform leaves found by WrapPreserve3DListInternal in nsDisplayOpacities with the correct opacity.

Not trivial though.
FWIW, the current spec says an opacity other than 1 forces transform-style: flat:

The following CSS property values require the user agent to create a flattened representation of the descendant elements before they can be applied, and therefore override the behavior of transform-style: preserve-3d:

. . .
opacity: any value other than 1.

If my understanding is correct, this paragraph concerns the flattening of descendant elements when opacity is not 1.

The issue here is different : it deals with the preservation (or not) of the 3d-ordering of child elements inside an opaque father element with when one child has simultaneously an opacity < 1 and a preserve-3d transform style (actually the latest may come from some inherited rule).
This bug seriously affects a very useful product called impress.js - which is set to become a viable replacement in the future for products such as Prezi. It's a 3D slide presentation library. It uses opacity to highlight the active slide and hide other slides. Because of the bug, non-focus slides that are behind the active slide appear in front instead and even make 'holes' in the active slide. It's a mess and really does need fixing please!
An example with impress.js :
Firefox is my favorite navigator. It would be really nice if i could make my impress.js presentation with it! :-)
PLEASE find way out to this bug :'-)
This appears to be fixed in Nightly (Firefox 45), probably because of bug 1097464.

That bug is on Aurora currently, so this should be fixed when Firefox 44 releases.
I can still reproduce this in Firefox 50.1.0 on OS X. Should also note that setting overflow: hidden; on an element that also has a transform-style: preserve-3d; style applied has the same effect as setting another opacity than 1.
You need to log in before you can comment on or make changes to this bug.