Richard
Richard

Reputation: 65600

Bug in CSS3 rotateY transition on Safari?

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;
}

Upvotes: 15

Views: 25852

Answers (6)

Bob
Bob

Reputation: 96

On the "back" side element that is translated 180 deg in Y, I added a 1px Z translation and it fixed my Safari bug.

transform: rotateY(180deg) translateZ(1px);

If the front & back elements are in the same z-index in Safari, this bug seems to be present.

There is a CodePen here where you can remove then translateZ(1px) and watch the bug show up. In my example case, the back side of the element has in "input" and "button" and the left half of both the input and button don't work due to the Safari bug.

See working code example here:

Codepen Example

Upvotes: 1

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

Upvotes: 3

joshuaai
joshuaai

Reputation: 41

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().

Upvotes: 2

ADavies
ADavies

Reputation: 21

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

Upvotes: 2

MorganIsBatman
MorganIsBatman

Reputation: 1010

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 :)

Upvotes: 2

ndm
ndm

Reputation: 60503

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/

Upvotes: 38

Related Questions