css z-index utracony po przekształceniu webkita translate3d

98

Mam dwa absolutnie ustawione elementy div, które się nakładają. Oba mają ustawione wartości indeksu z za pośrednictwem css. Używam translate3dWebKit przekształcić animowanie tych elementów z ekranu, a następnie z powrotem na ekran. Po transformacji elementy nie przestrzegają już ustalonych z-indexwartości.

Czy ktoś może wyjaśnić, co dzieje się z kolejnością Z-index / stack elementów div, gdy wykonam na nich transformację webkita? I wyjaśnij, co mogę zrobić, aby zachować kolejność elementów div na stosie?

Oto więcej informacji o tym, jak dokonuję transformacji.

Przed transformacją każdy element otrzymuje te dwie wartości przejścia webkit ustawiane za pośrednictwem css (używam jQuery do wykonywania .css()wywołań funkcji:

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

Element jest następnie animowany przy użyciu translate3d -webkit-transform:

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

Przy okazji, próbowałem ustawić trzeci parametr translate3dna kilka różnych wartości, aby spróbować odtworzyć kolejność stosu w przestrzeni 3D, ale bez powodzenia.

Ponadto przeglądarki iPhone / iPad i Android są moją docelową przeglądarką, na której ten kod musi działać. Oba obsługują przejścia z webkitami.

Rafe
źródło
Czy możesz opublikować link, aby zobaczyć przykład?
Littlemad
1
Spotkałem ten sam problem. Mam jeden tag <iframe> ze stylem elementu wewnętrznego „-webkit-transform: translate3d (0,0,0)”, aby wymusić przyspieszenie 3D. Okazuje się, że zewnętrzna ramka z wyższym indeksem Z jest zawsze ukryta przez wewnętrzny element iframe. Po prostu wizualnie ukryty, mogę „kliknąć” niewidoczny element zewnętrzny. Dzieje się tak tylko w Mobile Safari.
Morgan Cheng,
Spędziłem 10 godzin, zastanawiając się, co powoduje, że mój kod nie działa. Ugh
Dikeneko

Odpowiedzi:

52

Może to być związane z: https://bugs.webkit.org/show_bug.cgi?id=61824

Zasadniczo, gdy zastosujesz transformację 3D na osi z, indeks z nie może być już uwzględniony (jesteś teraz na trójwymiarowej płaszczyźnie renderowania, użyj różnych wartości z). Jeśli chcesz wrócić do renderowania 2D dla elementów podrzędnych, użyj transform-style: flat;.

samy-delux
źródło
13
Zasadniczo, gdy zastosujesz transformację 3D na osi z, indeks z nie może być już uwzględniony (jesteś teraz na trójwymiarowej płaszczyźnie renderowania, użyj różnych wartości z). Jeśli chcesz wrócić do renderowania 2D dla elementów podrzędnych, użyj transform-style: flat;.
samy-delux
2
Więc w trybie "preserve-3d" musimy użyć osi z transformacji, aby ustawić kolejność, aw trybie płaskim powinniśmy użyć indeksu z. Błąd polega na tym, że indeks Z na safari jest uszkodzony w połączeniu z przyspieszonymi transformacjami sprzętowymi.
Steven Lu
1
nie działa. Działa tylko wtedy, gdy usunę animowane style według klasy.
fdrv
44

Jest to z całą pewnością związane z błędem zauważonym przez samy-delux. Powinno to dotyczyć tylko tych elementów, które są pozycjonowane jako bezwzględne lub względne. Aby rozwiązać ten problem, możesz zastosować następującą instrukcję css do każdego elementu, który jest umieszczony w ten sposób i powoduje problemy:

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

Spowoduje to zastosowanie przekształcenia do elementu bez faktycznego wykonywania transformacji, ale wpłynie na jego kolejność renderowania, tak aby znajdował się nad elementem powodującym problem.

divThis
źródło
Korzystając z przeglądarki Chrome (35.0.1916.114 m), stwierdziłem, że jeśli nie mam tej reguły, po odwróceniu elementu [transform: rotateY (180deg)], moduły obsługi kliknięć jQuery nie działają już dla tego elementu. Ponadto po przewróceniu pojawiają się problemy z artefaktami pozostającymi na ekranie, a zwłaszcza jeśli zmieniono ich krycie, chyba że istnieje translate3d! Ten artykuł pomógł sitepoint.com/fix-chrome-animation-flash-bug
Philip Murphy
2
To właśnie rozwiązało bardzo przyklejony problem, który dotyczył dwóch stałych elementów, z których jeden zawierał element przekształcony w 3D. Przekształcony element 3D w zasadzie przepełniłby się i znalazłby się na innym elemencie, aż do zastosowania powyższej poprawki.
Collin James,
1
nie działa. Działa tylko wtedy, gdy usunę animowane style według klasy.
fdrv
12

Trochę późno, ale spróbuj umieścić elementy, które straciły indeks Z, umieszczając następujące, miałem problem podczas wykonywania ostatnio paralaksy i to bardzo pomogło.

transform-style: preserve-3d;

Oszczędza to nakładania

transform: translate3d(0,0,0);

Na innych elementach, które bardziej obciążają GPU

RustyCollins
źródło
1
Gdy twoje elementy są trójwymiarowe, nie spodziewałbym się, że transformacja dodatkowo obciąży GPU. I tak trzeba wykonać obliczenia. Na czym to opierasz?
Micros,
7

Czekam na przykład

Czy próbowałeś wykonać skalę transformacji (1)? Pamiętam, że miałem podobny problem i musiałem zmienić kolejność elementów w html i użyć transformacji, której nie potrzebowałem tylko dlatego, że zmienił się indeks Z użycia transformacji.

Jeśli się nie mylę, za każdym razem, gdy używasz transformacji, staje się ona najwyższym dostępnym indeksem z, a jest on uporządkowany według najbliższego elementu html znajdującego się na początku tagu. A więc od góry do dołu.

Mam nadzieję, że ta pomoc

Littlemad
źródło
6

z-index będzie działać z elementami div przekształconymi w 3D, jeśli nadasz styl elementowi stosowanemu w stosie -webkit-transform: translateZ(0px);

Fragment na codepen -> http://codepen.io/mrmoje/pen/yLIul

W przykładzie przyciski stack upi stack downpodnoszą i opuszczają indeks Z stopki (+/- 1) względem obracanego elementu (w tym przypadku obraz).

mrmoje
źródło
nie można ponownie kliknąć
stosu
Hej @Moje, również zastanawiam się nad tym problemem. Nadal nie można ponownie kliknąć stosu.
alchuang
Dlaczego nie pomyślałem o dodaniu ujemnego indeksu z do przetłumaczonego elementu? Dzięki
Will
3

Nie udało mi się odtworzyć opisanego tutaj problemu. Niezależnie od tego, co robię, wartość indeksu z jest zachowywana podczas wszystkich przekształceń. Testuję przy użyciu Chromium (Google Chrome).

Trzeci argument funkcji translate3d manipuluje osią z elementu. Koncepcja jest podobna, ale nie dokładnie taka sama, jak w przypadku indeksu z ... Elementy o niższej osi z znajdują się pod elementami o wyższej wartości.

Wiem, że wypróbowałeś wartości trzeciego argumentu, aby pasowały do ​​zamierzonego indeksu z, ale problem polega na tym, że oś z nie wydaje się zmieniać podczas animacji CSS3. W poniższym przykładzie element najechany kursorem powinien znajdować się na górze, ale #element_a pozostaje na górze.

Jeśli dodam indeks z zarówno do zwykłego selektora, jak i do selektora: hover, wydaje się, że działa i pozwala na umieszczenie elementu na górze.

Chociaż nie jest to dokładnie to, czego szukałeś, to zachowanie zapewnia rozwiązanie. Wystarczy użyć translate3d i z-index, aby ustawić kolejność początkowego renderowania.

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

źródło
2
To zadziałało dla mnie - dzięki! Dodałem do elementu, który chcę być „z przodu”: -webkit-transform: translate3d (0, 0, 1px);
Sam Dutton
0

Innym sposobem obejścia tego jest to, że możesz utworzyć element nadrzędny i zastosować wszystkie inne przejścia z nim związane:

# 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

Rdza
źródło