css z-index lost after webkit transform translate3d
Asked Answered
C

8

107

I have two absolutely positioned div elements that overlap. Both have set z-index values via css. I use the translate3d webkit transform to animate these elements off the screen, and then back onto the screen. After the transform, the elements no longer respect their set z-index values.

Can anyone explain what happens to the z-index / stack-order of the div elements once I do a webkit transform on them? And explain what I can do to keep the stack-order of the div elements?

Here is some more information on how I am doing the transform.

Before the transform, each element gets these two webkit transition values set via css (I am using jQuery to do the .css() function calls:

element.css({ '-webkit-transition-duration': duration + 's' });
element.css({ '-webkit-transition-property': '-webkit-transform' });

The element is then animated using the translate3d -webkit-transform:

element.css({ '-webkit-transform': 'translate3d(' + hwDelta + 'px, 0, -1px)' });

Btw, I have tried setting the 3rd parameter of translate3d to several different values to try to replicate the stack-order in the 3d space, but to no luck.

Also, iPhone/iPad and Android browsers are my target browser that this code needs to run on. Both support webkit transitions.

Clowers answered 29/3, 2011 at 12:52 Comment(3)
Can you post a link to see the example?Countrywoman
I met same issue. I have one <iframe> tag with inside element style "-webkit-transform: translate3d(0,0,0)" to force 3d acceleration. It turns out that outside frame with higher z-index is always hidden by the inside iframe element. Just visual hidden, I can "click" on the invisible outside element. This only happens in Mobile Safari.Edbert
I spent 10h figuring out that was what was making my code not work. UghTrotta
L
59

This might be related to: https://bugs.webkit.org/show_bug.cgi?id=61824

Basically when you apply a 3D transform on the z-axis, the z-index can't be accounted for anymore (you're now in a 3 dimensional rendering plane, use different z-values). If you want to switch back to 2D rendering for child elements, use transform-style: flat;.

Lenoir answered 10/2, 2012 at 12:5 Comment(3)
Basically when you apply a 3D transform on the z-axis, the z-index can't be accounted for anymore (you're now in a 3 dimensional rendering plane, use different z-values). If you want to switch back to 2D rendering for child elements, use transform-style: flat;.Lenoir
So in "preserve-3d" mode we gotta use z-axis of transform to set order, and in flat mode we should use z-index. The bug is that z-index on safari is broken in combination with HW accelerated transforms.Sneak
doesnt work. Only work if I remove animated styls by class.Eclipse
K
46

This is most definitely related to the bug noted by samy-delux. This should only affect any elements which are positioned as absolute or relative. In order to remedy the issue, you can apply the following css statement to every element which is positioned this way and is causing issues:

-webkit-transform: translate3d(0,0,0);

This will apply the transform to the element without actually doing a transformation, but affecting its render order so it is above the element causing the issue.

Krell answered 2/3, 2012 at 21:14 Comment(3)
Using Chrome (35.0.1916.114 m), I found that if I didn't have this rule, after the element was flipped [transform: rotateY(180deg)], that the jQuery click handlers didn't work for that element any more. Also, after a flip, there are issues with artefacts being left on the screen and especially if they had their opacity changed, unless the translate3d is present! This article helped sitepoint.com/fix-chrome-animation-flash-bugMelanson
This just resolved a very sticky issue for me involving two fixed elements, one containing a 3d transformed element. The 3d transformed element would basically overflow and sit on top of the other element until the fix above was applied.Ipa
doesnt work. Only work if I remove animated styls by class.Eclipse
A
15

Bit Late to this but try putting on the elements that have lost their Z-index placing the following, I had an issue when doing some parallax stuff recently and this helped massively.

transform-style: preserve-3d;

This saves putting

transform: translate3d(0,0,0);

On other elements which puts more strain on the GPU

Antimonic answered 25/6, 2015 at 8:52 Comment(1)
When your elements are 3d, I would not expect a transform to put extra strain on the GPU. Calculations need to be made anyway. What are you basing this on?Datura
C
7

Waiting to see the example

Have you tried to do a transform scale(1)? I remember to had a similar problem, and I had to re-arrange the html order of elements, and utilise a transform that I didn't need it just because the z-index of the use of transform changed.

If I am not in error, every time that you use a transform, it become the highest z-index available, and it is ordered by the nearest element of html is to the start of the tag. So from up to below.

I hope that this help

Countrywoman answered 29/3, 2011 at 13:38 Comment(0)
P
6

z-index will work against 3d transformed divs if you style the stackable element with -webkit-transform: translateZ(0px);

Snippet on codepen -> http://codepen.io/mrmoje/pen/yLIul

In the example, the buttons stack up and stack down raise and lower the footer's z-index (+/-1) against the rotated element (an img in this case).

Partridgeberry answered 12/9, 2013 at 2:13 Comment(3)
the stack up can't be clicked againHundredpercenter
Hey @Moje i'm also wondering about this issue. The stack up still cannot be clicked again.Liberate
Why did I not think to add a negative z-index to the translated element? ThanksMethylal
M
3

I haven't been able to reproduce the problem you describe here. Regardless of what I do, the z-index value is retained throughout all transforms. I'm testing using Chromium (Google Chrome).

The third argument of the translate3d function manipulates the z-axis of the element. The concept is similar to, but not exactly the same as, the z-index... Elements with a lower z-axis are under elements with a higher value.

I know you tried values of the third argument to match your intended z-index, but the problem is that the z-axis doesn't seem to change during CSS3 animation. In the following example, the hovered element should be on top, but #element_a stays on top.

If I add a z-index to both the regular selector and the :hover selector, it seems to work and allow the hovered element to be top-most.

Although it's not exactly what you were looking for, this behavior provides a solution. You just need to use translate3d and z-index to set the order for the initial rendering.

<style>
    div {
        width: 300px;
        height: 150px;
        background-color: white;
        border: 5px outset gray;
        float: left;
        margin: 20px;
        -webkit-transition: 2s;
    }

    #element_a {
        -webkit-transform: translate3d(0, 0, 50px);
    }
    #element_b {
        -webkit-transform: translate3d(0, 0, 100px);
    }

    #element_a:hover {
        -webkit-transform: translate3d(100px, 0, 60px);
    }

    #element_b:hover {
        -webkit-transform: translate3d(-100px, 0, -60px);
    }
</style>
<body>
    <div id="element_a">
        <img src="http://www.google.com/intl/en_com/images/srpr/logo3w.png">
    </div>
    <div id="element_b">
        <img src="http://www.google.com/intl/en_com/images/srpr/logo3w.png">
    </div>
</body>
Martlet answered 28/12, 2011 at 14:52 Comment(1)
This worked for me – thanks! I added the following to the element I want to be 'in front': -webkit-transform: translate3d(0, 0, 1px);Miniaturist
G
1

I had this problem on iphone/ios where I had a dropdown menu that overlapped a leafletjs map but was being covered by the map. Noticed that the map had translate3d applied.

Added this to the dropdown element:

transform: translate3d(0,0,0);

...and it is fixed. Thank you stackoverflow people.

Gesture answered 14/7, 2021 at 18:38 Comment(0)
A
0

Another way around this is that you can create a parent element and apply all other transitions related to it:

# Apply transitions to a parent div
<div>
  # This image z-index -1 
  <img src="foo"/>

  # This image z-index -3
  <img src="bar"/>

  #This image z-index -2
  <img src="gg"/>
</div>

JsFiddle

Ada answered 22/8, 2017 at 19:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.