css z-index perdido após webkit transformar translate3d


98

Eu tenho dois elementos div absolutamente posicionados que se sobrepõem. Ambos definiram valores de índice z via css. Eu uso a translate3dtransformação do webkit para animar esses elementos fora da tela e, em seguida, de volta na tela. Após a transformação, os elementos não respeitam mais seus z-indexvalores definidos .

Alguém pode explicar o que acontece com o índice z / ordem de pilha dos elementos div depois que faço uma transformação do webkit neles? E explicar o que posso fazer para manter a ordem da pilha dos elementos div?

Aqui estão mais algumas informações sobre como estou fazendo a transformação.

Antes da transformação, cada elemento obtém esses dois valores de transição do webkit definidos via css (estou usando jQuery para fazer as .css()chamadas de função:

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

O elemento é então animado usando o translate3d -webkit-transform:

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

A propósito, eu tentei definir o terceiro parâmetro de translate3d com vários valores diferentes para tentar replicar a ordem de pilha no espaço 3D, mas sem sorte.

Além disso, os navegadores iPhone / iPad e Android são meus navegadores de destino em que este código precisa ser executado. Ambos suportam transições de webkit.


Você pode postar um link para ver o exemplo?
— Littlemad

1
Eu encontrei o mesmo problema. Eu tenho uma tag <iframe> com o estilo de elemento interno "-webkit-transform: translate3d (0,0,0)" para forçar a aceleração 3D. Acontece que o quadro externo com índice z mais alto está sempre oculto pelo elemento iframe interno. Apenas visualmente oculto, posso "clicar" no elemento invisível externo. Isso só acontece no Mobile Safari.
— Morgan Cheng

Passei 10h descobrindo que era isso que fazia meu código não funcionar. Ugh
— Dikeneko

Respostas:


52

Isso pode estar relacionado a: https://bugs.webkit.org/show_bug.cgi?id=61824

Basicamente, quando você aplica uma transformação 3D no eixo z, o índice z não pode mais ser contabilizado (agora você está em um plano de renderização tridimensional, use valores z diferentes). Se você quiser voltar para a renderização 2D para elementos filhos, use transform-style: flat;.


13
Basicamente, quando você aplica uma transformação 3D no eixo z, o índice z não pode mais ser contabilizado (agora você está em um plano de renderização tridimensional, use valores z diferentes). Se você quiser voltar para a renderização 2D para elementos filhos, use transform-style: flat;.
— samy-delux

2
Portanto, no modo "preserve-3d", temos que usar o eixo z da transformação para definir a ordem, e no modo plano, devemos usar o z-index. O bug é que o Z-index no Safari é quebrado em combinação com as transformações aceleradas de HW.
— Steven Lu

1
não funciona. Só funciona se eu remover estilos animados por classe.
— fdrv

44

Isso está definitivamente relacionado ao bug observado por samy-delux. Isso deve afetar apenas os elementos posicionados como absolutos ou relativos. Para solucionar o problema, você pode aplicar a seguinte instrução css a cada elemento posicionado dessa maneira e que esteja causando problemas:

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

Isso aplicará a transformação ao elemento sem realmente fazer uma transformação, mas afetando sua ordem de renderização para que fique acima do elemento que está causando o problema.


Usando o Chrome (35.0.1916.114 m), descobri que se eu não tivesse essa regra, depois que o elemento foi invertido [transform: rotateY (180deg)], os manipuladores de cliques jQuery não funcionaram mais para aquele elemento. Além disso, após uma virada, há problemas com artefatos sendo deixados na tela e especialmente se eles tiveram sua opacidade alterada, a menos que o translate3d esteja presente! Este artigo ajudou sitepoint.com/fix-chrome-animation-flash-bug
— Philip Murphy

2
Isso acabou de resolver um problema muito complicado para mim envolvendo dois elementos fixos, um contendo um elemento transformado em 3D. O elemento transformado em 3D basicamente transbordaria e ficaria em cima do outro elemento até que a correção acima fosse aplicada.
— Collin James

1
não funciona. Só funciona se eu remover estilos animados por classe.
— fdrv

12

Um pouco tarde para isso, mas tente colocar os elementos que perderam seu Z-index colocando o seguinte, tive um problema ao fazer algumas coisas de paralaxe recentemente e isso ajudou muito.

transform-style: preserve-3d;

Isso economiza colocação

transform: translate3d(0,0,0);

Em outros elementos que colocam mais pressão na GPU


1
Quando seus elementos são 3D, eu não esperaria que uma transformação colocasse pressão extra na GPU. Os cálculos precisam ser feitos de qualquer maneira. no que você está baseando isto?
— Micros

7

Esperando para ver o exemplo

Você já tentou fazer uma escala de transformação (1)? Lembro-me de ter tido um problema semelhante e tive que reorganizar a ordem html dos elementos e utilizar uma transformação que não precisava apenas porque o índice z do uso da transformação mudou.

Se eu não estiver errado, toda vez que você usar uma transformação, ela se tornará o índice z mais alto disponível e será ordenado pelo elemento html mais próximo ao início da tag. Então, de cima para baixo.

Espero que isso ajude


6

z-index funcionará contra divs transformados em 3D se você estilizar o elemento empilhável com -webkit-transform: translateZ(0px);

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

No exemplo, os botões stack upe stack downaumentam e diminuem o índice z do rodapé (+/- 1) em relação ao elemento girado (um img neste caso).


o empilhamento não pode ser clicado novamente
— clevertension

Ei @Moje, também estou pensando sobre esse problema. O empilhamento ainda não pode ser clicado novamente.
— alchuang

Por que não pensei em adicionar um índice z negativo ao elemento traduzido? Obrigado
— Will

3

Não consegui reproduzir o problema que você descreve aqui. Independentemente do que eu fizer, o valor do z-index é retido em todas as transformações. Estou testando usando Chromium (Google Chrome).

O terceiro argumento da função translate3d manipula o eixo z do elemento. O conceito é semelhante, mas não exatamente igual, ao índice z ... Os elementos com um eixo z inferior estão abaixo dos elementos com um valor superior.

Eu sei que você tentou valores do terceiro argumento para corresponder ao seu índice z pretendido, mas o problema é que o eixo z não parece mudar durante a animação CSS3. No exemplo a seguir, o elemento pairado deve estar no topo, mas #element_a permanece no topo.

Se eu adicionar um índice z ao seletor regular e ao seletor: hover, parece funcionar e permitir que o elemento pairado fique no topo.

Embora não seja exatamente o que você estava procurando, esse comportamento oferece uma solução. Você só precisa usar translate3d e z-index para definir a ordem da renderização 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
Isso funcionou para mim - obrigado! Eu adicionei o seguinte ao elemento que desejo estar 'na frente': -webkit-transform: translate3d (0, 0, 1px);
— Sam Dutton

0

Outra maneira de contornar isso é que você pode criar um elemento pai e aplicar todas as outras transições relacionadas a ele:

# 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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.