css z-index perdido después de la transformación webkit translate3d


98

Tengo dos elementos div absolutamente posicionados que se superponen. Ambos han establecido valores de índice z a través de css. Utilizo la translate3dtransformación de webkit para animar estos elementos fuera de la pantalla y luego volver a la pantalla. Después de la transformación, los elementos ya no respetan sus z-indexvalores establecidos .

¿Alguien puede explicar qué sucede con el z-index / stack-order de los elementos div una vez que hago una transformación webkit en ellos? ¿Y explicar qué puedo hacer para mantener el orden de pila de los elementos div?

Aquí hay más información sobre cómo estoy haciendo la transformación.

Antes de la transformación, cada elemento obtiene estos dos valores de transición de webkit establecidos a través de css (estoy usando jQuery para hacer las .css()llamadas de función:

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

Luego, el elemento se anima usando translate3d -webkit-transform:

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

Por cierto, he intentado configurar el tercer parámetro de translate3den varios valores diferentes para intentar replicar el orden de la pila en el espacio 3d, pero sin suerte.

Además, los navegadores de iPhone / iPad y Android son mi navegador de destino en el que este código debe ejecutarse. Ambos admiten transiciones de webkit.


¿Puedes publicar un enlace para ver el ejemplo?
Littlemad

1
Me encontré con el mismo problema. Tengo una etiqueta <iframe> con el estilo de elemento interior "-webkit-transform: translate3d (0,0,0)" para forzar la aceleración 3d. Resulta que el marco exterior con un índice Z más alto siempre está oculto por el elemento iframe interior. Solo visualmente oculto, puedo "hacer clic" en el elemento exterior invisible. Esto solo ocurre en Mobile Safari.
Morgan Cheng

Pasé 10 horas descubriendo que eso era lo que hacía que mi código no funcionara. Ugh
Dikeneko

Respuestas:


52

Esto podría estar relacionado con: https://bugs.webkit.org/show_bug.cgi?id=61824

Básicamente, cuando aplica una transformación 3D en el eje z, el índice z ya no se puede tener en cuenta (ahora se encuentra en un plano de representación tridimensional, use diferentes valores z). Si desea volver al renderizado 2D para elementos secundarios, use transform-style: flat;.


13
Básicamente, cuando aplica una transformación 3D en el eje z, el índice z ya no se puede tener en cuenta (ahora se encuentra en un plano de representación tridimensional, use diferentes valores z). Si desea volver al renderizado 2D para elementos secundarios, use transform-style: flat;.
samy-delux

2
Entonces, en el modo "preserve-3d", debemos usar el eje z de la transformación para establecer el orden, y en el modo plano, debemos usar el índice z. El error es que el índice z en safari está roto en combinación con transformaciones aceleradas de HW.
Steven Lu

1
no funciona. Solo funciona si elimino los estilos animados por clase.
fdrv

44

Esto está definitivamente relacionado con el error observado por samy-delux. Esto solo debería afectar a los elementos que estén posicionados como absolutos o relativos. Para solucionar el problema, puede aplicar la siguiente instrucción css a cada elemento que se coloca de esta manera y está causando problemas:

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

Esto aplicará la transformación al elemento sin hacer realmente una transformación, pero afectando su orden de renderizado, por lo que está por encima del elemento que causa el problema.


Usando Chrome (35.0.1916.114 m), descubrí que si no tenía esta regla, después de que el elemento se volteó [transform: rotateY (180deg)], los controladores de clic de jQuery ya no funcionaban para ese elemento. Además, después de un giro, hay problemas con los artefactos que se dejan en la pantalla y especialmente si se les cambió la opacidad, ¡a menos que el translate3d esté presente! Este artículo ayudó a sitepoint.com/fix-chrome-animation-flash-bug
Philip Murphy

2
Esto acaba de resolver un problema muy complicado para mí que involucra dos elementos fijos, uno que contiene un elemento transformado en 3D. El elemento transformado en 3D básicamente se desbordaría y se colocaría encima del otro elemento hasta que se aplicara la corrección anterior.
Collin James

1
no funciona. Solo funciona si elimino los estilos animados por clase.
fdrv

12

Un poco tarde para esto, pero intente poner los elementos que han perdido su índice Z colocando lo siguiente, tuve un problema al hacer algunas cosas de paralaje recientemente y esto ayudó enormemente.

transform-style: preserve-3d;

Esto ahorra poner

transform: translate3d(0,0,0);

Sobre otros elementos que ejercen más presión sobre la GPU


1
Cuando sus elementos son 3d, no esperaría que una transformación ejerza una presión adicional sobre la GPU. Los cálculos deben realizarse de todos modos. ¿En qué estás basando esto?
Micros

7

Esperando ver el ejemplo

¿Ha intentado hacer una escala de transformación (1)? Recuerdo que tuve un problema similar y tuve que reorganizar el orden html de los elementos y utilizar una transformación que no la necesitaba solo porque el índice z del uso de la transformación cambió.

Si no me equivoco, cada vez que usa una transformación, se convierte en el índice z más alto disponible, y está ordenado por el elemento más cercano de html al comienzo de la etiqueta. Entonces de arriba hacia abajo.

Espero que esto ayude


6

z-index funcionará contra divs transformados en 3D si diseña el elemento apilable con -webkit-transform: translateZ(0px);

Fragmento en codepen -> http://codepen.io/mrmoje/pen/yLIul

En el ejemplo, los botones stack upy stack downsuben y bajan el índice z del pie de página (+/- 1) contra el elemento girado (un img en este caso).


no se puede volver a hacer clic en la pila
clevertension

Hola @Moje, también me pregunto sobre este tema. Aún no se puede volver a hacer clic en la pila.
alchuang

¿Por qué no pensé en agregar un índice Z negativo al elemento traducido? Gracias
Will

3

No he podido reproducir el problema que describe aquí. Independientemente de lo que haga, el valor del índice z se conserva en todas las transformaciones. Estoy probando con Chromium (Google Chrome).

El tercer argumento de la función translate3d manipula el eje z del elemento. El concepto es similar, pero no exactamente igual, al índice z ... Los elementos con un eje z más bajo están debajo de los elementos con un valor más alto.

Sé que probaste los valores del tercer argumento para que coincidieran con el índice z deseado, pero el problema es que el eje z no parece cambiar durante la animación CSS3. En el siguiente ejemplo, el elemento flotante debería estar en la parte superior, pero #element_a permanece en la parte superior.

Si agrego un índice z tanto al selector regular como al selector: hover, parece funcionar y permitir que el elemento flotante esté en la parte superior.

Aunque no es exactamente lo que buscaba, este comportamiento proporciona una solución. Solo necesita usar translate3d y z-index para establecer el orden para la representación inicial.

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

2
Esto funcionó para mí, ¡gracias! Agregué lo siguiente al elemento que quiero estar 'al frente': -webkit-transform: translate3d (0, 0, 1px);
Sam Dutton

0

Otra forma de evitar esto es que puede crear un elemento padre y aplicar todas las demás transiciones relacionadas con él:

# 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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.