This is an archived snapshot of W3C's public bugzilla bug tracker, decommissioned in April 2019. Please see the home page for more details.

Bug 16349 - backface-visibility underdefined
Summary: backface-visibility underdefined
Status: RESOLVED FIXED
Alias: None
Product: CSS
Classification: Unclassified
Component: Transforms (show other bugs)
Version: unspecified
Hardware: All All
: P2 normal
Target Milestone: ---
Assignee: Simon Fraser
QA Contact: public-css-bugzilla
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-03-13 20:50 UTC by Aryeh Gregor
Modified: 2012-03-19 19:24 UTC (History)
6 users (show)

See Also:


Attachments

Description Aryeh Gregor 2012-03-13 20:50:30 UTC
"""
The visibility of an element with ‘backface-visibility: hidden’ is determined as follows:

1. Compute a matrix representing the accumulated transform from the viewport, taking the translations due to the CSS visual formatting mode, the perspective and transformation matrices into account, in a similar manner to the computation of the accumulated transform for an element in a 3D rendering context.

2. If the component of the matrix in row 3, column 3 is negative, then the element should be hidden, otherwise it is visible.

ISSUE 6: Is the relevant matrix here really relative to the viewport, or to the root of the 3D rendering context?
"""
http://dev.w3.org/csswg/css3-transforms/#backface-visibility-property

This needs to be resolved.  Testing in browsers:

* IE10 Developer Preview, Windows 8
* Firefox 13.0a1, Ubuntu 32-bit with nouveau/Gallium3D
* Chrome 19 dev, Ubuntu 32-bit with nouveau/Gallium3D (no GPU acceleration)
* Chrome 19 dev, Ubuntu 64-bit with Intel mesa (GPU acceleration)
* WebKit nightly r109732, Windows 8

Test-case 1:

data:text/html,<!DOCTYPE html>
<div style="height:100px;width:100px;background:lime">
<div style="height:100px;width:100px;background:red;
transform:rotatex(180deg);backface-visibility:hidden">
</div>
</div>

This should obviously display green.  All browsers get this right except Chrome without GPU acceleration, which I suspect doesn't support backface-visibility at all, so I exclude it from further testing.

Test-case 2:

data:text/html,<!DOCTYPE html>
<div style="height:100px;width:100px;background:lime;
transform:rotatex(180deg)">
<div style="height:100px;width:100px;background:red;
transform:rotatex(180deg);backface-visibility:hidden">
</div>
</div>

This displays green in all browsers except Chrome (with GPU acceleration), which displays red.  I think green is correct -- the matrix should be relative to the root of the 3D rendering context, which in this case is just one rotatex(180deg), since there's no preserve-3d.

Test-case 3:

data:text/html,<!DOCTYPE html>
<div style="height:100px;width:100px;background:lime">
<div style="transform:rotatex(60deg);transform-style:preserve-3d">
<div style="height:100px;width:100px;background:red;
transform:rotatex(60deg);backface-visibility:hidden">
</div></div></div>

This displays green in all tested browsers, except IE10, which displays a band of red because it doesn't support preserve-3d.  This matches the idea that the matrix is relative to the root of the 3D rendering context.

Test-case 4:

data:text/html,<!DOCTYPE html>
<style>div { width: 100px; height: 100px }</style>
<div style="transform: rotateX(180deg); background: red">
  <div style="backface-visibility: hidden; background: lime"></div>
</div>

This should display green: no transform affects the inner div.  It does display green in Firefox, Chrome, and Safari.  But in IE it displays red.  Presumably IE accumulates transforms up to the viewport, even though the transform-style is flat.

Test-case 5:

data:text/html,<!DOCTYPE html>
<style>div { width: 100px; height: 100px }</style>
<div style="transform: rotateX(180deg); transform-style: preserve-3d;
background: lime">
  <div style="backface-visibility: hidden; background: red"></div>
</div>

This displays green in Firefox, but red in Chrome and Safari.  It should display green, because the child div is rotated 180 degrees due to the preserve-3d, so it should be invisible.  (This is <https://bugzilla.mozilla.org/show_bug.cgi?id=730166>.)

Test-case 6:

data:text/html,<!DOCTYPE html>
<style>div { height: 100px; width: 100px }</style>
<div style="background: lime">
  <div style="background: red; backface-visibility: hidden;
  transform: scaleZ(-1)"></div>
</div>

This displays green in IE, Firefox, and Safari, but red in Chrome.  Per the current spec, Chrome is definitely wrong.  I wonder what alternative way of determining backface-visibility it's using.


I propose that the above quoted spec text be replaced with:

"""
The visibility of an element with ‘backface-visibility: hidden’ is determined as follows:

1. For an element in a 3D rendering context, compute its accumulated transformation matrix.  For an element not in a 3D rendering context, compute its transformation matrix.

2. If the component of the matrix in row 3, column 3 is negative, then the element should be hidden, otherwise it is visible.
"""

"accumulated transformation matrix" should be a hyperlink to the steps used to figure out the rendering of an element in a 3D rendering context.

This change will make green the correct answer in all of the test-cases I provided here.  Any objections?  (In particular, this appears to be exactly how Gecko behaves, but all other engines will need some changes.)
Comment 1 Simon Fraser 2012-03-13 20:55:43 UTC
I would help me greatly if your examples contained browser prefixes.

I think you'll find that Safari on Mac is the only browser to implement backface-visibility per-spec. I object to changing the meaning.
Comment 2 Aryeh Gregor 2012-03-14 17:21:53 UTC
Please say if Safari on Mac displays red in any of these cases, and if so, why you think it's right:

Test-case 1:

data:text/html,<!DOCTYPE html>
<div style="height:100px;width:100px;background:lime">
  <div style="height:100px;width:100px;background:red;
  -webkit-transform:rotatex(180deg);-webkit-backface-visibility:hidden">
  </div>
</div>

Test-case 2:

data:text/html,<!DOCTYPE html>
<div style="height:100px;width:100px;background:lime;
-webkit-transform:rotatex(180deg)">
  <div style="height:100px;width:100px;background:red;
  -webkit-transform:rotatex(180deg);
  -webkit-backface-visibility:hidden"></div>
</div>

Test-case 3:

data:text/html,<!DOCTYPE html>
<div style="height:100px;width:100px;background:lime">
  <div style="-webkit-transform:rotatex(60deg);
  -webkit-transform-style:preserve-3d">
    <div style="height:100px;width:100px;background:red;
    -webkit-transform:rotatex(60deg);-webkit-backface-visibility:hidden">
    </div>
  </div>
</div>

Test-case 4:

data:text/html,<!DOCTYPE html>
<style>div { width: 100px; height: 100px }</style>
<div style="-webkit-transform: rotateX(180deg); background: red">
  <div style="-webkit-backface-visibility: hidden; background: lime">
  </div>
</div>

Test-case 5:

data:text/html,<!DOCTYPE html>
<style>div { width: 100px; height: 100px }</style>
<div style="-webkit-transform: rotateX(180deg);
-webkit-transform-style: preserve-3d; background: lime">
  <div style="-webkit-backface-visibility: hidden; background: red">
  </div>
</div>

Test-case 6:

data:text/html,<!DOCTYPE html>
<style>div { height: 100px; width: 100px }</style>
<div style="background: lime">
  <div style="background: red; -webkit-backface-visibility: hidden;
  -webkit-transform: scaleZ(-1)"></div>
</div>

WebKit nightly on Windows 8 displays red in test-case 5, which I think is a bug.  (It gets all the rest right.)  In support of the fact that this is a bug, adding -webkit-transform: scale(1) to the inner div in that test-case makes both the WebKit nightly and Chrome-with-GPU-acceleration display green.  Firefox had this bug too until version 13; the problem is that it was assuming that since there was no transform specified on the element, it didn't have to pay attention to 3D rendering separately from the parent, so it didn't look at backface-visibility.

If Safari on Mac gets all of these test-cases right, then it probably matches my proposed spec change too.
Comment 3 Simon Fraser 2012-03-14 18:03:20 UTC
(In reply to comment #2)
> Please say if Safari on Mac displays red in any of these cases, and if so, why
> you think it's right:
> 
> Test-case 5:
> 
> data:text/html,<!DOCTYPE html>
> <style>div { width: 100px; height: 100px }</style>
> <div style="-webkit-transform: rotateX(180deg);
> -webkit-transform-style: preserve-3d; background: lime">
>   <div style="-webkit-backface-visibility: hidden; background: red">
>   </div>
> </div>

> WebKit nightly on Windows 8 displays red in test-case 5, which I think is a
> bug.  (It gets all the rest right.)  In support of the fact that this is a bug,
> adding -webkit-transform: scale(1) to the inner div in that test-case makes
> both the WebKit nightly and Chrome-with-GPU-acceleration display green. 
> Firefox had this bug too until version 13; the problem is that it was assuming
> that since there was no transform specified on the element, it didn't have to
> pay attention to 3D rendering separately from the parent, so it didn't look at
> backface-visibility.
> 
> If Safari on Mac gets all of these test-cases right, then it probably matches
> my proposed spec change too.

Agreed; this is a bug. position:relative also works around it.

I'm trying to find out exactly what Safari's implementation does. This example:

data:text/html,<!DOCTYPE html>
<style>div { width: 100px; height: 100px } </style>
<div style="-webkit-transform: rotateX(180deg);">
  <div style="-webkit-transform-style: preserve-3d; background: lime">
    <div id="bf" style="-webkit-backface-visibility: hidden; background: red; width: 50px; margin-left: 30px; position: relative;">Test</div>
  </div>
</div>

implies that it's as you've written.
Comment 4 Aryeh Gregor 2012-03-14 18:15:15 UTC
Do you agree with my proposed spec change, then?
Comment 5 Simon Fraser 2012-03-14 18:32:56 UTC
I am fine with your spec text. It turns out to match the Safari impl.

I'm fixing the bug mentioned above via https://bugs.webkit.org/show_bug.cgi?id=81134.