webkit-transform breaks z-index on Safari
Asked Answered
P

4

26

Problem

I'm trying to make a layer appear like it's a wall falling down, revealing the layer behind it. I've setup two fixed div positions. The "Wall" div has a z-index of 9999, the "Background" div has a z-index of 0;

In Webkit browsers (Safari/IOS) that I've tested, it seems like once the animation starts on the "wall", the z-indexes are lost or ignored, causing the "wall" layer to abruptly disappear behind the background div.

Any ideas on how to preserve the z-indexes of the layers? Thanks in advance!

Example Code (note: jsFiddle at the bottom)

HTML Code

<div id="wall">
    This is the wall
</div>

<div id="background">
    This is the background
</div>

<button id="start" style="float: right;">
Flip Down
</button>

Some javascript to enable the button

$('#start').click(function(){
    alert('Should Fall Down like a wall, revealing the background');
    $('#wall').addClass('animated flipDown');
});

CSS Code (cribbed from animate.css)

#wall{
    background-color: #F00;
    width: 100px;
    height: 100px;
    position:fixed;
    top:0;
    left:0;
    z-index: 9999;
}

#background{
    background-color: #00F;
    width: 100px;
    height: 100px; 
    position:fixed;
    top:0;
    left:0;
    z-index: 0;
}

.animated {
  -webkit-animation-duration: 1s;
  animation-duration: 1s;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}


/*** flipDown ***/

@-webkit-keyframes flipDown {
  0% {
    -webkit-transform: perspective(400px) rotateX(0deg);
    transform: perspective(400px) rotateX(0deg);
    -webkit-transform-style: flat;
    opacity: 1;
  }

  100% {
    -webkit-transform: perspective(400px) rotateX(90deg);
    transform: perspective(400px) rotateX(90deg);
    -webkit-transform-style: flat;
    opacity: 1;
  }
}

@keyframes flipDown {
  0% {
    -webkit-transform: perspective(400px) rotateX(0deg);
    -ms-transform: perspective(400px) rotateX(0deg);
    transform: perspective(400px) rotateX(0deg);
    opacity: 1;
  }

  100% {
    -webkit-transform: perspective(400px) rotateX(90deg);
    -ms-transform: perspective(400px) rotateX(90deg);
    transform: perspective(400px) rotateX(90deg);
    opacity: 0;
  }
}

.flipDown {
    -webkit-animation-name: flipDown;
    animation-name: flipDown;
    -webkit-backface-visibility: visible !important;
    -ms-backface-visibility: visible !important;
    backface-visibility: visible !important;
    -webkit-transform-origin: bottom;
    -ms-transform-origin: bottom;
    transform-origin: bottom;
}

jsFiddle

http://jsfiddle.net/3mHe2/2/

Check out the differences in Safari vs Chrome.

Palmapalmaceous answered 24/3, 2014 at 22:2 Comment(1)
Hmmm, I had a similar problem with transition but when I switched to using animation it workedMutineer
S
29

My rotating element wasn't suitable to have a neighbour to the background, but I fixed it by applying

transform: translateZ(1000px);
transform-style: preserve-3d;

to the parent of the rotating element. Safari now thinks it's 1000px infront of the background.

Shaffer answered 25/6, 2014 at 14:33 Comment(0)
P
25

Found a solution. Hopefully this helps someone in the future.

It turns out that there is a "bug" in the safari versions of webkit. When a 3d css animation is playing, the original z-indexes are lost. Instead, it seems like the animating pieces are put into a separate z-index "group" that is separate from the rest of the z-indexes of the DOM.

The solution is to join the backdrop div and the wall div into the same z-index group by wrapping it in a div with a webkit-transform that doesn't change anything. That causes the backdrop and wall to be children of the wrapper div and the z-indexing of the respective children are preserved.

<div id="wrapper" style="-webkit-transform: translate3d(0px, 0px, 0px);">
    <div id="wall">
        This is the wall
    </div>

    <div id="background">
        This is the background
    </div>
</div>

I believe it is the same or similar issue to this:

css z-index lost after webkit transform translate3d

Palmapalmaceous answered 27/3, 2014 at 18:43 Comment(1)
Worked beautifully and seems non-invasive.Hamamelidaceous
L
11

I ran into this issue and nothing would fix it until i added perspective to the parent container of the item that should be behind.

.wrap{
    perspective: 1000px;
}
Lorineloriner answered 20/10, 2015 at 20:41 Comment(0)
B
0

In my case I was able to solve the issue by applying translateZ to the parent and translate scale to the child.

.parent {
  transform: translateZ(22px);
}
.child {
  transform: scale(0.955);
}
Bravin answered 18/7, 2022 at 13:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.