CSS-Z-Index nach Webkit-Transformation translate3d verloren

98

Ich habe zwei absolut positionierte div-Elemente, die sich überlappen. Beide haben Z-Index-Werte über CSS festgelegt. Ich verwende die translate3dWebkit-Transformation, um diese Elemente vom Bildschirm zu animieren und dann wieder auf den Bildschirm zu gelangen. Nach der Transformation respektieren die Elemente ihre eingestellten z-indexWerte nicht mehr .

Kann jemand erklären, was mit dem Z-Index / der Stapelreihenfolge der div-Elemente passiert, wenn ich eine Webkit-Transformation für sie durchführe? Und erklären Sie, was ich tun kann, um die Stapelreihenfolge der div-Elemente beizubehalten?

Hier finden Sie weitere Informationen dazu, wie ich die Transformation durchführe.

Vor der Transformation erhält jedes Element diese beiden Webkit-Übergangswerte, die über CSS festgelegt wurden (ich verwende jQuery, um die .css()Funktionsaufrufe auszuführen :

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

Das Element wird dann mit der translate3d -webkit-transform animiert:

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

Übrigens habe ich versucht, den 3. Parameter translate3dauf mehrere verschiedene Werte zu setzen, um zu versuchen, die Stapelreihenfolge im 3D-Raum zu replizieren, aber ohne Glück.

Außerdem sind iPhone / iPad- und Android-Browser mein Zielbrowser, auf dem dieser Code ausgeführt werden muss. Beide unterstützen Webkit-Übergänge.

Rafe
quelle
Können Sie einen Link posten, um das Beispiel zu sehen?
Littlemad
1
Ich habe das gleiche Problem getroffen. Ich habe ein <iframe> -Tag mit dem inneren Elementstil "-webkit-transform: translate3d (0,0,0)", um die 3D-Beschleunigung zu erzwingen. Es stellt sich heraus, dass der äußere Frame mit dem höheren Z-Index immer vom inneren Iframe-Element verdeckt wird. Nur visuell versteckt, kann ich auf das unsichtbare äußere Element "klicken". Dies geschieht nur in Mobile Safari.
Morgan Cheng
Ich habe 10 Stunden damit verbracht herauszufinden, dass mein Code dadurch nicht funktioniert hat. Ugh
Dikeneko

Antworten:

52

Dies könnte mit Folgendem zusammenhängen: https://bugs.webkit.org/show_bug.cgi?id=61824

Grundsätzlich kann beim Anwenden einer 3D-Transformation auf die Z-Achse der Z-Index nicht mehr berücksichtigt werden (Sie befinden sich jetzt in einer dreidimensionalen Renderebene und verwenden unterschiedliche Z-Werte). Wenn Sie für untergeordnete Elemente wieder zum 2D-Rendering wechseln möchten, verwenden Sie transform-style: flat;.

Samy-Delux
quelle
13
Grundsätzlich kann beim Anwenden einer 3D-Transformation auf die Z-Achse der Z-Index nicht mehr berücksichtigt werden (Sie befinden sich jetzt in einer dreidimensionalen Renderebene und verwenden unterschiedliche Z-Werte). Wenn Sie für untergeordnete Elemente wieder zum 2D-Rendering wechseln möchten, verwenden Sie transform-style: flat;.
Samy-Delux
2
Im Modus "Bewahren-3D" müssen wir die Z-Achse der Transformation verwenden, um die Reihenfolge festzulegen, und im flachen Modus sollten wir den Z-Index verwenden. Der Fehler ist, dass der Z-Index auf Safari in Kombination mit HW-beschleunigten Transformationen gebrochen ist.
Steven Lu
1
funktioniert nicht Funktioniert nur, wenn ich animierte Stile nach Klasse entferne.
fdrv
44

Dies hängt definitiv mit dem von samy-delux festgestellten Fehler zusammen. Dies sollte nur Elemente betreffen, die als absolut oder relativ positioniert sind. Um das Problem zu beheben, können Sie die folgende CSS-Anweisung auf jedes Element anwenden, das auf diese Weise positioniert ist und Probleme verursacht:

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

Dadurch wird die Transformation auf das Element angewendet, ohne tatsächlich eine Transformation durchzuführen, die Renderreihenfolge wird jedoch so beeinflusst, dass sie über dem Element liegt, das das Problem verursacht.

divThis
quelle
Bei Verwendung von Chrome (35.0.1916.114 m) stellte ich fest, dass die jQuery-Klick-Handler für dieses Element nicht mehr funktionierten, wenn ich diese Regel nicht hatte, nachdem das Element umgedreht wurde [transform: rotateY (180deg)]. Außerdem gibt es nach einem Flip Probleme mit Artefakten auf dem Bildschirm, insbesondere wenn die Deckkraft geändert wurde, es sei denn, translate3d ist vorhanden! Dieser Artikel half sitepoint.com/fix-chrome-animation-flash-bug
Philip Murphy
2
Dies löste gerade ein sehr heikles Problem für mich, das zwei feste Elemente umfasste, von denen eines ein 3D-transformiertes Element enthielt. Das 3D-transformierte Element würde im Grunde überlaufen und auf dem anderen Element sitzen, bis der obige Fix angewendet wurde.
Collin James
1
funktioniert nicht Funktioniert nur, wenn ich animierte Stile nach Klasse entferne.
fdrv
12

Etwas spät dazu, aber versuchen Sie, die Elemente, die ihren Z-Index verloren haben, wie folgt zu platzieren. Ich hatte kürzlich ein Problem, als ich einige Parallaxen machte, und dies half massiv.

transform-style: preserve-3d;

Das spart Putten

transform: translate3d(0,0,0);

Auf andere Elemente, die die GPU stärker belasten

RustyCollins
quelle
1
Wenn Ihre Elemente 3D sind, würde ich nicht erwarten, dass eine Transformation die GPU zusätzlich belastet. Berechnungen müssen trotzdem gemacht werden. Worauf stützen Sie sich?
Micros
7

Warten auf das Beispiel

Haben Sie versucht, eine Transformationsskala (1) durchzuführen? Ich erinnere mich, dass ich ein ähnliches Problem hatte, und ich musste die HTML-Reihenfolge der Elemente neu anordnen und eine Transformation verwenden, die ich nicht brauchte, nur weil sich der Z-Index der Verwendung der Transformation geändert hatte.

Wenn ich mich nicht irre, wird jedes Mal, wenn Sie eine Transformation verwenden, diese zum höchsten verfügbaren Z-Index, und sie wird nach dem nächstgelegenen HTML-Element am Anfang des Tags sortiert. Also von oben nach unten.

Ich hoffe das hilft

Littlemad
quelle
6

z-index funktioniert gegen 3D-transformierte Divs, wenn Sie das stapelbare Element mit formatieren -webkit-transform: translateZ(0px);

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

Im Beispiel heben und senken die Tasten stack upund stack downerhöhen und senken den Z-Index der Fußzeile (+/- 1) gegen das gedrehte Element (in diesem Fall ein Bild).

mrmoje
quelle
Der Stapel kann nicht erneut angeklickt werden
clevertension
Hey @ Moje, ich wundere mich auch über dieses Problem. Der Stapel kann immer noch nicht erneut angeklickt werden.
Alchuang
Warum habe ich nicht daran gedacht, dem übersetzten Element einen negativen Z-Index hinzuzufügen? Vielen Dank
Will
3

Ich konnte das hier beschriebene Problem nicht reproduzieren. Unabhängig davon, was ich mache, bleibt der Z-Index-Wert bei allen Transformationen erhalten. Ich teste mit Chromium (Google Chrome).

Das dritte Argument der Funktion translate3d manipuliert die z-Achse des Elements. Das Konzept ähnelt dem Z-Index, ist jedoch nicht genau mit diesem identisch. Elemente mit einer niedrigeren Z-Achse befinden sich unter Elementen mit einem höheren Wert.

Ich weiß, dass Sie versucht haben, die Werte des dritten Arguments an Ihren beabsichtigten Z-Index anzupassen, aber das Problem ist, dass sich die Z-Achse während der CSS3-Animation nicht zu ändern scheint. Im folgenden Beispiel sollte sich das schwebende Element oben befinden, aber #element_a bleibt oben.

Wenn ich sowohl dem regulären Selektor als auch dem: hover-Selektor einen Z-Index hinzufüge, scheint dies zu funktionieren und zuzulassen, dass das schwebende Element ganz oben steht.

Obwohl es nicht genau das ist, wonach Sie gesucht haben, bietet dieses Verhalten eine Lösung. Sie müssen nur translate3d und z-index verwenden, um die Reihenfolge für das anfängliche Rendern festzulegen.

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

quelle
2
Das hat bei mir funktioniert - danke! Ich habe dem Element, das ich 'vorne' sein möchte, Folgendes hinzugefügt: -webkit-transform: translate3d (0, 0, 1px);
Sam Dutton
0

Eine andere Möglichkeit, dies zu umgehen, besteht darin, dass Sie ein übergeordnetes Element erstellen und alle anderen damit verbundenen Übergänge anwenden können:

# 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

Rost
quelle