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.

Rafe
fonte
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;.

samy-delux
fonte
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.

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

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

Littlemad
fonte
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).

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

fonte
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

Ferrugem
fonte