Jump to content
Search Community

Safari vs Chrome Rendering 2D over 3D

themepunch test
Moderator Tag

Go to solution Solved by themepunch,

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hi Folks,


this question is following me since a long time.  The rendering of 3d Objects in Safari and Chrome is just different.

Hard to say what is better, however i am looking for a solution and hope you can give me a clear Answer here.


As you can see in my CodePen example (

See the Pen zvomGW by themepunch (@themepunch) on CodePen

)  the rendering of these animation in Safari and Chrome just totally different. 


My goal is to make it look in safari as it looks like in Chrome.  The Green box (should be a simple 2d content) should always overlay the 3d flipping element.  


Hope you guys have some smart idea which works later dynamic in more complex situation also. 


Thanks a lot and again, and still: i love GreenSock ! The best Engine ever ! 


Krisztian from ThemePunch



See the Pen GpNzZR by jonathan (@jonathan) on CodePen

Link to comment
Share on other sites

Hello ThemePunch,


But this is a CSS stacking context issue. Which is different than z-index. and z-axis issue.


Just tested with my example on Safari ..and the .box2 is always above .box1 .. test example below on Safari:


See the Pen avBRGX by jonathan (@jonathan) on CodePen


You could try forcing your .box2 element into a new stacking context that is independent of z-index. But independent on the new stacking context you give it. Even if you had z-index one million, it still would not affect the stacking with regular z-index.


Also if you add (translateZ) z:210 on .box2 since your rotating with perspective. The .box1 rotation and perspective are pushing the rotated face across your .box2 element ;)


Normally you would just increase z (translateZ) by half of your rotated elements width. You have to add z:210 due to when your .box1 rotates it is intersecting with .box1 on rotation. And with perspective it forces even further into the 3d plane that .box2 is on. You would have to play with how much translateZ (z) would be on the element, depending on the amount of perspective used.


( half element width 150 + extra padding = 210 )


For example, adjusting (decreasing) the opacity on the element by just a little can make it so that element stays below the other elements. In your case you want .box1 to always be below .box2. So you would give .box1 an opacity of 0.99 on your tween or via the GSAP set() method. Also adding z (translateZ) since you have rotation and perspective, that will cross over the 3d plane in z-axis

// due to rotation and perspective you must give
// .box2 translateZ = z:210
TweenMax.set(".box2",{opacity:1, z:210});
// add this to give .box1 new stacking context
// forces below element .box2

TweenMax.fromTo('.box1', 5,{
  rotationX: -360,
  rotationY: -70
}, {
  rotationX: 50,
  rotationY: 30

Stacking Context is different that z-index. Stacking Context can be achieved by the following:

  • the root element (HTML),
  • positioned (absolutely or relatively) with a z-index value other than "auto",
  • a flex item with a z-index value other than "auto",that is the parent element display: flex|inline-flex,
  • elements with an opacity value less than 1. (See the specification for opacity),
  • elements with a transform value other than "none",
  • elements with a mix-blend-mode value other than "normal",
  • elements with a filter value other than "none",
  • elements with isolation set to "isolate",
  • position: fixed
  • specifing any attribute above in will-change even you don't write themselves directly (See this post)
  • elements with -webkit-overflow-scrolling set to "touch"

Also keep in mind if you are using the latest version of GSAP, or a version 1.13.1 and above..  you no longer need to use a jQuery selector in the tween target, since GSAP now uses document.querySelectorAll() as the default selector.


Keep in mind you could try anything else in the list above to organize existing and new stacking contexts. But you will have to see which one works best for your project. Changing the opacity below the other elements opacity of 1 is the easiest though.


Also be mindful that in Safari -webkit-overflow-scrolling: touch; is not set on other elements you don't want a stacking context on. You can switch those elements to -webkit-overflow-scrolling: none;


I also forgot to mention you might need to adjust the z-axis (translateZ) more or less when you test your animation.



Stacking  Context: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context

Stacking without Z-index: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Stacking_without_z-index

CSS Perspective: https://developer.mozilla.org/en-US/docs/Web/CSS/perspective


I hope this helps! :)

  • Like 4
Link to comment
Share on other sites

Thank you for your feedback, really appreciate it, however i am afraid this is not the solution i am looking for or i did not understand you very well.

Let me describe this a bit better:


Imagine .box2 would have further content (i.e. text, images etc.).  

The content of box2 should not be influenced. (It should not be blurred, zoomed, scaled at all) however translating that element along the z axis would of course change the rendering and scaling of those elements also. See i.e. Codepen:

See the Pen rOWogG by themepunch (@themepunch) on CodePen


This is what i am working on right now "example"  as you can see i am rotating different layers parallax.  The goal is to add more layers over the current "3D world" in an independent container which should not be 3D transformed and should not be cropped by the rotated elements under it.


Short sad, can you please show me on the CodePen example how to modificate the box2 div without having influence on the font size i.e ? 


Thank you,


Krisztian from ThemePunch

Link to comment
Share on other sites

I see what you mean now, thanks for the clarification


Couldn't you just have .box1 have its transform 2d or 3d and then instead of pushing .box2 forward via z-axis (translateZ).. push the transformed .box1 back in a negative z (translateZ) value to compensate. Leaving .box2 with no transform


TweenMax.set(".box1",{opacity:0.99, z:-210}); // reverse translateZ (z) in the negative

So the transformed effect and element are separate from the content element.


Do you know what I mean? :)

  • Like 2
Link to comment
Share on other sites

You are quick :)  Unfortunately that would push the background away, and would not fill any more the container as it should.  If you take a look on the live example i am working on, you see that the 3D world fills the container.  You may know our product, a Slider Builder, where dynamic content is added by the users, and we must find a possibility to create independent 3d and 2d containers overlapping each other, without the needs to push the content aways along the z-axis. 


I am looking for a working solution in Safari since a long time, and someway i cant find any :(  I learned a lot from the example above you wrote, however this still not fills the requirements i have here.  Do you think there is any other solution for Safari ?  (seems that Google Chrome and Firefox have no problem with it).


Thanks again for your amazing quick support ! 



Link to comment
Share on other sites

Hmmm.. have you tried maybe using skewX or skewY instead to mimic a 3D effect, and then turn off 3d for the element that have skew on it, with force3D:false.


Also maybe using transformPerspective ( transform: perspective(1600) ) instead of the perspective property. transformPerspective function would be placed on the element you want perspective on. whereas perspective (which you are using) is placed on the parent of the element and add perspective on its children.


I have seen many webkit bugs that are triggered by using perspective on a parent, since it affects all children. Versus just using transformPersective on each element you want perspective on.


Perspective CSS property: https://developer.mozilla.org/en-US/docs/Web/CSS/perspective

Transform Perspective function: https://developer.mozilla.org/en-US/docs/Web/CSS/transform


Maybe that will help? or not? :)

Link to comment
Share on other sites

Thank you again for your feedback. Yes, we used to use Skew before 3D transforms were introduced in CSS3.  The quality difference is huge, and we would love to stay on the level what 3D rotating delivers for us of course.   I played around with the perspective, however this did not bring me further yet. 


I am really looking for a solution where 2d/3d Context can be grouped and rendered in one Stacking Container, and other 2d/3d context can be rendered in another Stacking container, and these both containers can be added under/over each other without cropping parts of them.


This is how Google Chrome manage it in my CodePen Example above. Basically the goal is still the same. Having the Green Box over the Rose Box in Safari, without the needs to move the Green or rose Box along the z axis. (Sizes should stay as they are)


All further inputs and ideas are very welcome ! 

Link to comment
Share on other sites

I can't acess Safari right now, but if you manually create the 3d transform it should work. Try this out. Just drag the control points around and it shouldn't intersect with the green box.


See the Pen e8f4cb8391f473891d05cbe60d21cbba by osublake (@osublake) on CodePen


I've used that matrix to animate 3d objects in the past. It's based off this article, and the code is from this gist. You don't need jQuery UI. I just copied everything from the gist, but it's pretty easy to modify to work with whatever it is you are trying to animate.

  • Like 1
Link to comment
Share on other sites

I am really thankful for your idea however this overshoot the mark a lot.  That would make impossible to create clean 3d rotations on multiple elements without the needs to build high complex math functions to calculate distorts, skews etc.  Remember this should work on multiple stacked content with relative rotated elements.


I would like to have a solution where custom dynamic animation can be generated on one group of elements, and other group of elements with a simple overly can be added to overlap this animation with simple texts without the needs to move these along the z-axis and / or to skew / fake 3d effects.     


Hope you guys still have some ideas ?  I wrote to Safari Developer Forum also in the hope that i get some clever answer on this.


Thank you,



Link to comment
Share on other sites

I'm confused on what you want? :huh:  You say you want a 3D effect but without moving on the z-axis. If you don't want to include the z-axis than its 2D, just x and y. And you don't want a fake 3D effect, mimicking 3D with 2D. So I'm not sure what your end goal is since you want a 3D world with 3D transforms, but with no z-axis, which tells me no 3D. Your best bet is to just separate your 3D effect element with a 2D effect element in front of it. ;)  But I'm really confused :blink:

  • Like 1
Link to comment
Share on other sites

@Jonathan, please take a look again on this

See the Pen vNxYgG by themepunch (@themepunch) on CodePen

    Check it in Google Chrome and in Safari to compare the differences.


I think the question is quite simple. How to set the Green Box overlapping the Rosa Box always in Safari !! if you take a look in Safari you see how the Rotated Rosa element crops/cut the green box due its 3d depth.   Again, here is the slider i am working on: EXAMPLE The plan is to add Content over the Slider, without cutting / cropping the content which is overlapping the slider in Safari !  And why i say 2d, 3d ?  Because the Content which is overlapping the Slider should be a none scaled, none transformed content ! 


@diaco, the solution you present in your other forum unfortunately does not help.  I tried in the Codepen example above, and it had no any influence on the demo yet.  Please take a look on the Modificated CodePen from your other Forum :

See the Pen QjpWmx by themepunch (@themepunch) on CodePen

  Adding the preserve-3d transform style to the image wrapper shows the same failure in Safari.


Maybe you wish to give one more chance to this ? Would really appreciate it ! 



Link to comment
Share on other sites

  • Solution

This seems to work now:


Moving the .box2 out of .world:

<div class="world">
  <div class="box1">
    <div class="box1_a"></div>
<div class="box2">
  <p>Some Text</p>

and adding .world and .box2 both transform-style flat:

TweenMax.set(jQuery('.world, .box2'), {
  perspective: 1600,
  transformStyle: "flat"


and setting the .box1 its own perspective and the transform-style preserve-3d: 

TweenMax.fromTo(jQuery('.box1'), 5, {
  rotationX: -360,
  rotationY: -70,
  transformStyle: "preserve-3d"
}, {
  rotationX: 50,
  rotationY: 30,
  repeat: -1

solves the problem, and let the .box2 set over/under the 3d rendered group by its z-index now also in Safari, not just in Chrome !! 


So, i am happy and ok now. Sorry for being a pain.. guys, and hope this helps somebody else also one day.  


This is how the Code Pan looks like now: 

See the Pen WQpNBg by themepunch (@themepunch) on CodePen


Cheers and thanks,


Krisztian from ThemePunch

Link to comment
Share on other sites

Yep that is why i recommended above to try and seperate your 3d and 2d elemenrs and to use transformPerspective (transform perspective function) on the individual elements you wanted perspective on. Instead of using the perspective property, which gives perspective to all its children, that would effect .box2. Like in your original example. As a rule of thumb any time you are not animating your object and it is at rest.. it is best to change the transform-style property to flat, especially if it is an element you don't want a 3d effect on. ;)

  • Like 2
Link to comment
Share on other sites

Unfortunately having different perspective alone is not enough. You still need to split them into two containers within two different level (like world and box2 in my last example). Moving box1 and box2 on the same level, even if they have their own transform perspective is not working in Safari for me.


So the solution i posted above is for me the only working way right now, (which is good and enough for my needs :) )


Thank you again for all your support and input here, really appreciate it ! You guys are quick and very helpful as always ! 


Keep up the great work ! 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...