I've been building a prism rotation effect using 3D transforms. The transform-origin-z
property seemed best for transforming the faces of the prism, but Safari 5 and Mobile Safari inexplicably stretch my element, even when no transform is applied. Firefox 12 and Chrome 18 work correctly.
Live Demo
Full Prism Demo
I'm interested in understanding why this happens. Should I avoid transform-origin-z
entirely, or is there some workaround for Safari and Mobile Safari?
<style>
/* other browser prefixes omitted for brevity */
.container {
margin: 50px;
border: 2px solid #00f;
height: 50px;
-webkit-perspective: 500px;
}
.face {
height: 50px;
background-color: rgba(255,0,0,0.5);
-webkit-transform-origin: center center -25px;
-webkit-transform: translate3d(0,0,0);
}
</style>
<div class="container">
<div class="face"></div>
</div>
it seems like this is a bug in Safari.
Chrome moves the transformation-center over the Z-axis, Safari leaves this center were it was, but moves the object itself over the Z-axis.
The object therefore is zoomed in Safari, and seems bigger.
I would avoid the transform-origin (on Z-axis) for now and work with translate-Z to produce the same effect.
Example:
http://jsfiddle.net/willemvb/GuhcC/3/
I believe the following explanation answers the "why" Safari is doing what it is
I do not have access to Safari for testing, but as I read the specifications for the perspective
property (the same spec page you point to), it states:
The ‘perspective’ property applies the same transform as the
perspective() transform function, except that it applies only
to the positioned or transformed children of the element, not to the
transform on the element itself.
Update on how I read the above spec
The ‘perspective’ property applies the same transform as the perspective() transform function
This tells me a perspective transform is going to be done just as if transform: perspective(500px)
were applied in this case.
except that it applies only to the positioned or transformed children of the element
This tells me the perspective transform is going to be applied to child elements, in this case .face
. Here, there seems to be some ambiguity. Is this saying the perspective should only be applied if another transform is done on the child element? And, does the tranform-origin
property count as a transform being done to the child (especially since it is this value that relates directly to the perspective
transform)? It is at this point of ambiguity that the browsers seem to differ. Safari is doing the perspective
transform because the child element has tranform-origin
set to -25px
, whereas the others apparently are not (at least, not until the actual other transform
does something else to the .face
during the animation).
not to the transform on the element itself
This tells me the z=0
of .container
is irrelevant, because the transform from this property is not affecting .container
, but rather .container
's children (i.e. .face
).
So Safari appears to be taking the position that your .face
always has a transform applied because you have set .container
to have -webkit-perspective: 500px;
, so there is always a perspective
transform being applied to the child elements (.face
in your case).
Note that if you take away the animation, and apply an actual transform: perspective(500px)
to the .face
you will see the same result in Firefox or Chrome as what you experience in Safari with your code.
So I think actually, Safari may be doing it correctly, and Firefox and Chrome perhaps are not. The spec has some ambiguity. The other two browsers perhaps should be still applying the perspective transform based off .container
like Safari does, but certainly appear to not be, whereas Safari obviously appears to be.
To eliminate the issue (not have it "stick out" when "at rest"), you probably need to
- Animate the
transform-origin
itself at the beginning of your animation (and reset to 0
afterwards), OR...
- Animate the
perspective
value itself to be 0
when "at rest" and 500px
when animating.
My guess is #1 will be easier to implement, but I don't know for sure.
I don't know why this worked for me. Seem to work on all browsers. Basically I think I am canceling the css declarations effect.
.container {
perspective: 500px;
transform-origin: 50% 50% 25px;
}