15

I am showing a modal popup using CSS3 transitions (largely borrowed from Effeckt.css). It works well in all modern browsers except Safari. In Safari, the movement is OK, but the background-color snaps in unevenly.

This is the code, the problem is visible in Safari on OSX: http://jsfiddle.net/eJsZx/4/

A screenshot of the problem before it resolves itself. You can see that half the div is correctly colored white, half is still transparent.

enter image description here

This is the relevant part of the CSS (.effeckt-show and .md-effect-8 are applied when the button is clicked, to show the modal):

.effeckt-modal {
  visibility: hidden;
  -webkit-backface-visibility: hidden;
  -ms-backface-visibility: hidden;
  -o-backface-visibility: hidden;
  backface-visibility: hidden;
  background: white;
}
.md-effect-8 {
  -webkit-perspective: 1300px;
  -ms-perspective: 1300px;
  -o-perspective: 1300px;
  perspective: 1300px;
  -webkit-transform-style: preserve-3d;
  -ms-transform-style: preserve-3d;
  -o-transform-style: preserve-3d;
  transform-style: preserve-3d;
}
.md-effect-8 .effeckt-modal {
  -webkit-transform: rotateY(-70deg);
  -ms-transform: rotateY(-70deg);
  -o-transform: rotateY(-70deg);
  transform: rotateY(-70deg);
  -webkit-transition: all 500ms;
  -o-transition: all 500ms;
  transition: all 500ms;
  opacity: 0;
}
.effeckt-show.md-effect-8 .effeckt-modal {
    -webkit-transform: rotateY(0deg);
    -ms-transform: rotateY(0deg);
    -o-transform: rotateY(0deg);
    transform: rotateY(0deg);
    opacity: 1;
}
Richard
  • 62,943
  • 126
  • 334
  • 542
  • I believe https://stackoverflow.com/questions/22621544/webkit-transform-breaks-z-index-on-safari contains some clues on why this is happening. – Thomas Jul 05 '21 at 10:25

5 Answers5

38

As far as I can tell it's a bug, yes, Safari is rendering intersection where it shouldn't.

For some time I thought Safari is doing it right by always rendering intersection of elements, but as far as I understand the specs, only elements in the same 3d rendering context should intersect, and that would be children of elements with a transform-style of preserve-3d.

So far the only workaround I found (only tested on Windows yet where Safari shows the same behaviour) is to translate the underlying elements away on the z-axis. Without perspective being applied it won't actually translate, but Safari/Webkit seems to think it does (which probably is because it mistakenly treats the element as if it were in the same 3d rendering context as the actually transformed dialog) and so the elements do no longer intersect.

.effeckt-overlay {
    position: fixed;
    width: 100%;
    height: 100%;
    visibility: hidden;
    top: 0;
    left: 0;
    opacity: 0;
    -webkit-transition: 500ms;
    -o-transition: 500ms;
    transition: 500ms;
    z-index: 1000;
    background: rgba(0, 0, 0, 0.5);

    -webkit-transform: translateZ(-1000px);
}

http://jsfiddle.net/eJsZx/5/

Community
  • 1
  • 1
ndm
  • 59,784
  • 9
  • 71
  • 110
  • 3
    For my solution http://jsfiddle.net/ardeezstyle/cdcnyfr6/, I've to make a small change `-webkit-transform: translateZ(1000px);` and it worked like a charm. My +1. Thanks #ndm – Rupam Datta Oct 27 '14 at 10:24
  • 2
    Saved my butt! Thank you :) FWIW, `-1000px` isn't necessary if you don't have crazy Z translations already, you can get away with `-1px`. – Jason Mar 03 '15 at 18:00
  • This bug still exists in 2019! Is there a solution that doesn't involve Z translations? Because I _am_ using perspective, a Z translation would be visible. – Thomas Jun 15 '19 at 14:41
  • @Thomas I've never found another solution, but I also didn't really look into it much anymore. Can't test it right now as Safari for Windows is dead, and I have no MacOS VM set up currently, sorry... – ndm Jun 15 '19 at 15:49
  • I got it to work by putting a `z-index: 0` on the parent element, but my situation is slightly different so I'll leave this as a comment, rather than posting an answer. – Thomas Jun 15 '19 at 16:53
  • 2
    My solution was to put my element in a wrapper to which I applied `-webkit-transform: translateZ(1000px);` so my whole animation is above the rest instead of tricking the navigator into thinking the parent is under using a negative value, I found that easier. – rAthus Jul 11 '19 at 09:46
  • z-axis means the axis that one can not see and goes inside. is this the thing? so are we moving them further away on that axis? – Shashank Bhatt Jul 07 '21 at 10:41
  • In my opinion, `translateZ` is similar to `z-index` but in 3d-space. – Jerry Ni Apr 21 '23 at 08:54
2

I found this issue when trying to find a solution to a problem I was experiencing in Safari (Mac and iOS), where a y-rotated svg only displayed its right half for no apparent reason.

In my case, the svg was a child of a fixed-position div, and I found that both position: fixed and position: absolute on the parent caused half the svg to disappear.

Neither changing z indexes, perspective, nor translate-z seemed to solve the issue. But randomly, adding a new div around my svg and setting its background-color solved the problem. I hope this helps the next person :)

MorganIsBatman
  • 1,000
  • 8
  • 13
2

In my case, adding z-index: 0 to the parent element fixed it as per Thomas's suggestion.

ADavies
  • 21
  • 1
2

None of the solutions above worked for me. In the end, this is a bug with rotate on Safari that Chrome previously had but fixed. The answer here was what solved it for me - using scale() rather than rotate().

joshuaai
  • 41
  • 3
2

In my case, it worked to put transform: translateZ(0); on the parent container. The object itself is an image.