Worauf man bei der Arbeit mit CSS 3D achten sollte

Avatar of Ana Tudor
Von Ana Tudor am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Ich habe schon immer 3D-Geometrie geliebt. Ich begann mit CSS 3D-Transformationen zu experimentieren, sobald ich merkte, dass die Unterstützung in CSS anständig wurde. Aber während es sich natürlich anfühlte, Transformationen zu verwenden, um 2D-Formen zu erstellen und sie in 3D zu bewegen/rotieren, um Polyeder zu erstellen, gab es einige Dinge, die mich anfangs stolpern ließen. Ich dachte, ich könnte über die Dinge schreiben, die mich überraschten und die Herausforderungen, auf die ich stieß, damit Sie die gleichen vermeiden können.

3D-Rendering-Kontext

Ich erinnere mich deutlich, dass ich das erste Mal an diesem Abend darauf gestoßen bin, als mich Neugier packte und ich einen schnellen Test schreiben wollte, um zu sehen, wie Browser Ebenen-Schnittpunkte behandeln. Der Test enthielt zwei Ebenen-Elemente

<div class='plane'></div>
<div class='plane'></div>

Sie waren gleich groß, absolut auf dem Bildschirm zentriert und erhielten einen Hintergrund, damit sie sichtbar waren

$dim: 40vmin;

.plane {
  position: absolute;
  top: 50%; left: 50%;
  margin: -.5*$dim;
  width: $dim; height: $dim;
  background: #ee8c25;
}

Die Szene war das gesamte `body`-Element, das den gesamten Viewport abdeckte und eine `perspective` erhielt, sodass alles, was weiter entfernt war, kleiner und alles Nähere größer erschien

body {
  margin: 0;
  height: 100vh;
  perspective: 40em;
}

Um die Ebenen-Schnittpunkte tatsächlich zu testen, erhielt das zweite Ebenen-Element eine `rotateY()`-Transformation und einen anderen Hintergrund

.plane:last-child {
  transform: rotateY(60deg);
  background: #d14730;
}

Das Ergebnis war enttäuschend. Es schien, dass kein Browser Ebenen-Schnittpunkte richtig behandeln kann

Sehen Sie den Stift test plane intersection (WRONG!) von Ana Tudor (@thebabydino) auf CodePen.

Aber ich hatte Unrecht. Das ist genau das, was der von mir geschriebene Code ergeben sollte. Was ich hätte tun sollen, war, meine beiden Ebenen in denselben 3D-Rendering-Kontext zu legen. Wenn Sie mit 3D-Rendering-Kontexten nicht vertraut sind, sind sie nicht sehr unterschiedlich von Stacking Contexts. So wie wir Elemente nicht über `z-index` ordnen können, wenn sie sich nicht im selben Stacking-Kontext befinden, können 3D-transformierte Elemente nicht in 3D-Reihenfolge angeordnet oder zur Schnittstelle gebracht werden, wenn sie sich nicht im selben 3D-Rendering-Kontext befinden.

Der einfachste Weg, sicherzustellen, dass sie sich im selben 3D-Rendering-Kontext befinden, ist, sie in ein anderes Element zu legen

<div class='assembly'>
    <div class='plane'></div>
    <div class='plane'></div>   
</div>

Und dann dieses enthaltende Element absolut in der Mitte der Szene positionieren und `transform-style: preserve-3d` darauf setzen

div { position: absolute; }

.assembly {
    top: 50%; left: 50%;
    transform-style: preserve-3d;
}

Das löst das Problem

Sehen Sie den Stift test plane intersection (CORRECT) von Ana Tudor (@thebabydino) auf CodePen.

Wenn Sie Firefox verwenden, um die obige Demo anzuzeigen, können Sie die Ebenen immer noch nicht wie erwartet miteinander schneiden, da Firefox dies noch nicht richtig hinbekommt. Aber Sie sollten sie in WebKit-Browsern und in Edge schneiden sehen. **Update**: Dieses Problem ist in Firefox 55+ behoben.

Nun fragen Sie sich vielleicht, warum überhaupt das Hinzufügen dieses enthaltenden Elements, sollte nicht einfach das Hinzufügen von `transform-style: preserve-3d` zur Szene (dem `body`-Element in unserem Fall) funktionieren? Nun, in diesem speziellen Fall, wenn wir diese eine Regel hinzufügen und nichts anderes zur ursprünglichen Demo, funktioniert es (es sei denn, Sie sehen es in Firefox 54 oder älter)

Sehen Sie den Stift test plane intersection (working, BUT…) von Ana Tudor (@thebabydino) auf CodePen.

Wenn wir 3D auf einer tatsächlichen Webseite verwenden wollen, wird unsere Szene wahrscheinlich nicht das `body`-Element sein und wir werden wahrscheinlich andere Eigenschaften auf der Szene hinzufügen wollen. Eigenschaften, die damit interferieren könnten.

Dinge, die 3D zerstören (oder zu Abflachung führen)

Nehmen wir an, unsere Szene ist ein weiteres `div` auf der Seite und wir haben andere Dinge herum

Sehen Sie den Stift two planes in smaller scene #0 von Ana Tudor (@thebabydino) auf CodePen.

Ich habe auch ein paar weitere Transformationen auf der zweiten Ebene hinzugefügt, um deutlicher zu machen, dass sie aus der Szene herausragt. Das ist etwas, das wir nicht wollen. Wir wollen den Text lesen können, mit Steuerelementen interagieren, die wir dort vielleicht haben, und so weiter.

1) `overflow`

Die erste Idee, die einem in den Sinn kommt, ist einfach `overflow: hidden` auf der Szene zu setzen. Wenn wir das tun, verlieren wir jedoch unsere schöne 3D-Schnittstelle

Das Problem.

Das liegt daran, dass die Angabe von `overflow` mit einem anderen Wert als `visible` effektiv den Wert von `transform-style` auf `flat` erzwingt, auch wenn wir ihn explizit auf `preserve-3d` gesetzt haben. Die Verwendung eines Containers bedeutet also, etwas mehr Code zu schreiben, kann uns aber viel Kopfzerbrechen ersparen.

Die Lösung.

Deshalb platziere ich jetzt alles in einer Szene in einem enthaltenden Element, auch wenn dieses Element nicht in 3D transformiert wird. Betrachten Sie zum Beispiel die folgende Demo

Sehen Sie den Stift blue hex helix candy (pure CSS 3D) von Ana Tudor (@thebabydino) auf CodePen.

Alle rotierenden Sechseck-Säulen sind innerhalb eines `.helix`-Elements platziert

<div class='helix'>
    <div class='col'>
        <!-- all the hexagons inside a column -->
    </div>
    <!-- the other columns -->
</div>

Dieses `.helix`-Element hat keine anderen Stile (direkt gesetzt oder geerbt) außer denen, die sicherstellen, dass die gesamte Anordnung absolut in der Mitte des Viewports positioniert ist und dass alle Säulen sich im selben 3D-Rendering-Kontext befinden

div {
    position: absolute;
    transform-style: preserve-3d;
}

.helix { top: 50%; left: 50%; }

Das liegt daran, dass ich `overflow: hidden` auf der Szene (in diesem Fall dem `body`-Element) setze, da die Größe der Sechsecke nicht vom Viewport abhängt, und ich nicht weiß, ob sie nach außen reichen (und Scrollbalken verursachen, was ich nicht will) oder nicht.

Ich muss gestehen, dass ich dieses Problem mehr als einmal hatte, bevor ich meine Lektion gelernt habe. Zu meiner Verteidigung gibt es Situationen, in denen die Auswirkung von `overflow: hidden` nicht so offensichtlich zu sein scheint.

transform-style: preserve-3d teilt dem Browser mit, dass die 3D-transformierten Kinder des Elements, auf das es angewendet wird, nicht in die Ebene ihres Elternelements (des Elements, auf das `transform-style: preserve-3d` angewendet wird) abgeflacht werden sollen. Es scheint also intuitiv sinnvoll, dass auch die Anwendung von `overflow: hidden` auf dasselbe Element dies rückgängig macht und verhindert, dass Kinder aus der Ebene ihres Elternelements ausbrechen.

Aber manchmal kann ein 3D-transformiertes Kind immer noch in der Ebene seines Elternelements liegen. Betrachten Sie den folgenden Fall: Wir haben eine Karte mit zwei Seiten

<div class='card'>
    <div class='face'>front</div>
    <div class='face'>back</div>
</div>

Wir positionieren sie alle absolut in der Mitte der Szene (in diesem Fall das `body`-Element), geben sowohl der Karte als auch ihren Seiten die gleichen Abmessungen, setzen `transform-style: preserve-3d` auf die Karte, setzen `backface-visibility: hidden` auf die Seiten und drehen die zweite um eine halbe Umdrehung um ihre vertikale Achse

$dim: 40vmin;

div {
    position: absolute;
    width: $dim; height: $dim;
}

.card {
    top: 50%; left: 50%;
    margin: -.5*$dim;
    transform-style: preserve-3d;
}

.face {
    backface-visibility: hidden;
    background: #ee8c25;

    &:last-child {
        transform: rotateY(.5turn);
        background: #d14730;
    }
}

Die Demo ist unten zu sehen

Sehen Sie den Stift card #0 von Ana Tudor (@thebabydino) auf CodePen.

Beide Seiten liegen immer noch in der Ebene ihres Elternelements, es ist nur so, dass die Rückseite um eine halbe Umdrehung um ihre vertikale Achse gedreht ist. Sie zeigt in die entgegengesetzte Richtung, aber sie liegt immer noch in derselben Ebene. Bisher scheint alles in Ordnung zu sein.

Nun wollen wir, dass die Seiten nicht rechteckig sind. Der einfachste Weg, das zu ändern, ist, der Karte `border-radius: 50%` zu geben. Aber das scheint überhaupt nichts zu bewirken.

Lassen Sie uns also `overflow: hidden` darauf setzen

Sehen Sie den Stift card #2 von Ana Tudor (@thebabydino) auf CodePen.

Ups, das hat unsere 3D-Karte kaputt gemacht! Da wir das nicht tun können, müssen wir die Ecken der Seiten abrunden

.face { border-radius: 50%; }

Sehen Sie den Stift card #3 von Ana Tudor (@thebabydino) auf CodePen.

In diesem Fall ist die Methode zur Lösung des Problems noch einfacher als die, die die Probleme verursacht. Aber was, wenn wir eine andere Form wollten, zum Beispiel ein regelmäßiges Achteck? Ein regelmäßiges Achteck ist mit zwei Elementen (oder einem Element und einem Pseudo-Element) ziemlich einfach zu erreichen

<div class='octagon'>
    <div class='inner'></div>
</div>

Wir geben ihnen beiden die gleichen Abmessungen, drehen das `.inner`-Element um `45deg`, geben ihm einen Hintergrund, damit wir es sehen können, und setzen dann `overflow: hidden` auf das `.octagon`-Element

$dim: 65vmin;

div { width: $dim; height: $dim; }

.octagon { overflow: hidden; }

.inner {
    transform: rotate(45deg);
    background: #ee8c25;
}

Das Ergebnis ist in folgendem Pen zu sehen

Sehen Sie den Stift how to: basic regular octagon (pure CSS) von Ana Tudor (@thebabydino) auf CodePen.

Wenn wir Text hinzufügen…

<div class='octagon'>
  <div class='inner'>octagon</div>
</div>

Er wird überhaupt nicht angezeigt.

Das Problem ist, dass er in einer der Ecken abgeschnitten wird. Wir machen ihn also größer, richten ihn horizontal mit `text-align: center` aus und bringen ihn vertikal in die Mitte, indem wir ihm eine Zeilenhöhe geben, die der Abmessung unseres `.octagon`- (oder `.inner`-) Elements entspricht

.inner {
    font: 10vmin/ #{$dim} sans-serif;
    text-align: center;
}

Jetzt sieht es viel besser aus, aber der Text ist immer noch gedreht, da wir eine Drehung auf dem `.inner`-Element eingestellt haben

Sehen Sie den Stift octagon with text #1 von Ana Tudor (@thebabydino) auf CodePen.

Um dieses Problem zu lösen, fügen wir eine Drehung hinzu, um sie umzukehren (mit gleichem Winkel, aber in die entgegengesetzte Richtung, also negativ) auf dem `.octagon`-Element

.octagon { transform: rotate(-45deg); }

Wir haben ein Achteck mit Text!

Sehen Sie den Stift octagon with text – final! von Ana Tudor (@thebabydino) auf CodePen.

Sehen wir uns nun an, wie wir das anwenden können, wenn wir eine Karte mit achteckigen Seiten haben wollen. Wir können `overflow: hidden` nicht auf die Karte selbst anwenden (wodurch sie die Rolle des `.octagon`-Elements spielt, während die Seiten wie `.inner`-Elemente wären), da dies die Dinge kaputt machen würde und wir keine schöne 3D-Karte mit zwei verschiedenen Seiten mehr hätten

Sehen Sie den Stift card #4 von Ana Tudor (@thebabydino) auf CodePen.

Stattdessen müssen wir jede Seite die Rolle des `.octagon`-Elements spielen lassen und ein Pseudo-Element verwenden, das die Rolle des inneren Elements spielt

.face {
    overflow: hidden;
    transform: rotate(45deg);
    backface-visibility: hidden;

    &:before {
        left: 0;
        transform: rotate(-45deg);
        background: #ee8c25;
        content: 'front';
    }

    &:last-child {
        transform: rotateY(.5turn) rotate(45deg);

        &:before {
            background: #d14730;
            content: 'back'
        }
    }
}

Dies gibt uns das Ergebnis, das wir angestrebt haben

Sehen Sie den Stift card #5 von Ana Tudor (@thebabydino) auf CodePen.

2) `clip-path`

Eine weitere Eigenschaft, die ähnliche Probleme verursachen kann, ist `clip-path`. Zurück zu unserem Kartenbeispiel, wir können sie nicht dreieckig machen, indem wir `clip-path` auf das `.card`-Element selbst anwenden, da wir brauchen, dass es ein 3D-transformiertes Kind hat, die zweite Seite. Wir sollten es stattdessen auf die Kartenseiten anwenden

.face { clip-path: polygon(100% 50%, 0 0, 0 100%); }

Beachten Sie, dass die `clip-path`-Eigenschaft immer noch das `-webkit-`-Präfix für WebKit-Browser benötigt, die Einstellung des Flags `layout.css.clip-path-shapes.enabled` auf `true` in `about:config` für Firefox 47-53 (das Flag ist in Firefox 54+ standardmäßig auf `true` gesetzt) und noch nicht in Edge unterstützt wird (aber Sie können für die Implementierung abstimmen).

Das Ergebnis der Hinzufügung der obigen Codezeile würde wie folgt aussehen

Sehen Sie den Stift card #6 von Ana Tudor (@thebabydino) auf CodePen.

Keine 3D-Probleme, aber es sieht wirklich seltsam aus. Wenn die Karte von vorne gesehen ein nach rechts zeigendes Dreieck ist, dann sollte sie von hinten gesehen nach links zeigen. Aber das tut sie nicht, sie zeigt auch nach rechts. Eine Lösung für dieses Problem wäre die Verwendung unterschiedlicher `clip-path`-Werte für jede der Seiten. Schneiden Sie die Vorderseite mit demselben nach rechts zeigenden Dreieck und schneiden Sie die Rückseite mit einem anderen nach links zeigenden Dreieck

.face:last-child { clip-path: polygon(0 50%, 100% 0, 100% 100%); }

Das Ergebnis ist genau das, was wir wollten

Sehen Sie den Stift card #7 von Ana Tudor (@thebabydino) auf CodePen.

Beachten Sie, dass ich auch den `text-align`-Wert geändert habe: `left` standardmäßig für die Vorderseite und `right` für die Rückseite.

Alternativ könnten wir auch `scaleX(-1)` zur Transformationskette der Rückseite hinzufügen (wenn Sie eine Erinnerung brauchen, wie Skalierung funktioniert, schauen Sie sich diese interaktive Demo an)

.face:last-child { transform: rotateY(.5turn) scaleX(-1); }

Sehen Sie den Stift card #8 von Ana Tudor (@thebabydino) auf CodePen.

Die Form sieht in diesem Fall gut aus, aber der Text ist spiegelverkehrt. Das bedeutet, dass wir den Text und den Hintergrund auf ein Pseudo-Element legen, auf dem wir die Skalierung auf dem `.face`-Element umkehren. Das Umkehren einer Skalierung des Faktors `f` bedeutet, eine Skalierung des Faktors `1/f` einzustellen. In unserem Fall ist der Faktor `f` `-1`, also ist der Wert, den wir für die Skalierung auf dem Pseudo-Element suchen, `1/-1 = -1`.

.face:last-child:before {
    transform: scaleX(-1);
    background: #d14730;
    text-align: right;
    content: 'back';
}

Das Endergebnis ist in diesem Stift zu sehen

Sehen Sie den Stift card #9 von Ana Tudor (@thebabydino) auf CodePen.

Maskierungs-Eigenschaften, die auf andere Werte als `none` gesetzt sind, können ebenfalls den verwendeten Wert von `transform-style` auf `flat` erzwingen, genau wie `overflow` oder `clip-path`, wenn sie auf andere Werte als `visible` bzw. `none` gesetzt sind.

3) `opacity`

Das ist eine unerwartete Sache.

Es ist auch eine relativ neue Änderung in der Spezifikation, damit die Auswirkung von `opacity` kleiner als `1` auf 3D-Rendering-Kontexte mit der auf Stacking-Kontexte übereinstimmt. Deshalb erzwingt sub-unitäre `opacity` in Edge oder Safari noch keine Abflachung... noch nicht! In Chrome, Opera und Firefox hat sie jedoch diesen Effekt.

Betrachten Sie die folgende Demo, eine Gruppe von Würfeln, die sich zusammen in 3D drehen

Sehen Sie den Stift cube assembly #0 von Ana Tudor (@thebabydino) auf CodePen.

Strukturell bedeutet dies ein `.assembly`-Element, das eine Reihe von `.cube`-Elementen enthält, jedes davon mit 6 Seiten

<div class='assembly'>
  <div class='cube'>
    <div class='cube__face'></div>
    <!-- five more cube faces -->
  </div>
  <!-- more cubes, each with 6 faces -->
</div>

Sagen wir nun, wir möchten, dass die Würfel halbtransparent sind. Das können wir nicht tun

.cube { opacity: .5; }

Dies führt dazu, dass der `transform-style`-Wert auf den `.cube`-Elementen auf `flat` gezwungen wird, obwohl wir ihn auf `preserve-3d` gesetzt haben, was dazu führt, dass die Würfelseiten in die Ebenen ihrer `.cube`-Eltern abgeflacht werden. Vorerst nur in Chrome, Opera und Firefox, aber der Rest der Browser wird dies in Zukunft auch implementieren.

Ergebnis, wenn Opazität keine Abflachung erzwingt (Edge, Safari)
Ergebnis, wenn Opazität Abflachung erzwingt (Chrome, Firefox, Opera, gemäß neuen Spezifikationsänderungen)

Wir können auch nicht `opacity: .5` auf das `.assembly`-Element anwenden, da wir auch `transform-style` darauf auf `preserve-3d` gesetzt haben. Also, wieder, das Ergebnis wird über Browser hinweg inkonsistent sein, da die neue Spezifikation Abflachung erzwingt und einige immer noch die alte befolgen (die das nicht tat).

Was wir ohne Probleme tun können, ist, `opacity: .5` auf die Würfelseiten-Elemente zu setzen

Sehen Sie den Stift
cube assembly #3
von CSS-Tricks (@css-tricks)
auf CodePen.

Wir könnten es auch auf dem Szenenelement setzen, aber beachten Sie, dass dies auch jeden Szenen-`background` oder Pseudo-Elemente beeinflussen würde, die wir vielleicht haben. Es würde auch nicht die einzelnen Würfel oder Seiten halbtransparent machen, nur die gesamte Anordnung. Und es erlaubt uns nicht, unterschiedliche Opazitätswerte für verschiedene Würfel zu haben.

Ergebnis, wenn Opacity: .5 auf die einzelnen Würfelseiten gesetzt wird
Ergebnis, wenn Opacity: .5 auf die Szene gesetzt wird

4) `filter`

Das ist auch eine Sache, die mich überrascht hat, aber anders als `opacity` ist sie nicht neu und die Ergebnisse sind browserübergreifend konsistent. Betrachten wir noch einmal das Beispiel mit den Würfeln. Sagen wir, wir wollen für jeden Würfel einen zufälligen anderen Farbton über `hue-rotate()` erzielen. Das Setzen eines `filter`-Wertes anders als `none` auf den Würfeln oder der Anordnung führt zu abgeflachten Darstellungen.

$n: 20; // number of cubes

@for $i from 0 to $n {
    $angle: random(360)*1deg;

    .cube:nth-child(#{$i + 1}) {
        filter: hue-rotate($angle);
    }
}

Beachten Sie, dass bis vor kurzem `filter` immer noch das `-webkit-`-Präfix für alle WebKit-Browser benötigte und dass, obwohl aktuelle Versionen aller gängigen Desktop-Browser es jetzt ohne Präfix unterstützen, die meisten mobilen Browser dieses Präfix immer noch benötigen.

Dies funktioniert, um jedem Würfel einen zufälligen Farbton zu geben, aber es flacht sie auch ab

Die Lösung in diesem Fall ist, den `filter` auf den Würfelseiten innerhalb der Schleife zu setzen

$n: 20; // number of cubes

@for $i from 0 to $n {
    $angle: random(360)*1deg;

    .cube:nth-child(#{$i + 1}) .cube__face {
        filter: hue-rotate($angle);
    }
}

Das gibt uns das, was wir wollten: Würfel in zufälligen Farbtönen und immer noch 3D, nicht abgeflacht

Sehen Sie den Stift
cube assembly #6
von CSS-Tricks (@css-tricks)
auf CodePen.

Wir können auch keinen `filter` auf die gesamte Anordnung setzen. Betrachten Sie die Situation, in der wir sie alle verschwommen haben wollen. Sagen wir, wir machen das so

.assembly { filter: blur(4px); }
Das Ergebnis ist, dass die gesamte Anordnung zusätzlich zum Verschwimmen in die Ebene der Anordnung abgeflacht wird. Edge ist die Ausnahme, alles verschwindet.

Was wir hier tun könnten, ist zu versuchen, den `blur()`-Filter auf die Seitenelemente anzuwenden, obwohl das Ergebnis nicht genau das wäre, als ob die einzelnen Seiten verschwommen wären, nicht die Würfel selbst. Es sieht auch fehlerhaft aus, wobei Blink-Browser Flackern und fehlende Seiten erfahren und durch den `blur()`-Filter merklich verlangsamt werden, während Edge alles komplett durcheinanderbringt. Firefox scheint hier am besten abzuschneiden.

Wir könnten auch versuchen, es auf die Szene anzuwenden, obwohl das fehlerhaft zu sein scheint (manchmal gibt es Flackern, Seiten verschwinden in Chrome und in Firefox, wo die gesamte Anordnung dann komplett verschwindet, während Edge nichts anzeigt).

Ich war überrascht, denn diese nächste einfachere Demo eines rotierenden Würfels hat auch einen `blur()`-Filter auf der Szene angewendet und es scheint größtenteils in Blink-Browsern und in Edge zu funktionieren. In Firefox wird jedoch nichts angezeigt.

Sehen Sie den Stift
gooey cubes (pure CSS 3D, no Firefox)
von CSS-Tricks (@css-tricks)
auf CodePen.

Insgesamt scheinen Filter in Kombination mit 3D oft problematisch zu sein, daher würde ich sagen, verwenden Sie sie mit Vorsicht.

5) `mix-blend-mode`

Sagen wir, wir haben ein `.container`-Element mit einem Art Regenbogen-`background`. Innerhalb dieses Elements haben wir ein `.mover`-Element mit einem Bild-`background`, sagen wir eine Brombeer-Torte. Der Klassenname hat das wahrscheinlich schon verraten, aber wir animieren die Position des `.mover`-Elements und setzen `mix-blend-mode: overlay` darauf. Das verleiht unserem Mover ein anderes Aussehen, je nachdem, über welchen Teil des `background` seines Elternelements er sich bewegt.

Sehen Sie den Stift orbiting pie blending in (blend modes!) von Ana Tudor (@thebabydino) auf CodePen.

Blend-Modi werden in Edge noch nicht unterstützt, daher funktionieren keine der Demos in diesem Abschnitt dort. Sie können jedoch für die Implementierung von `mix-blend-mode` abstimmen. Beachten Sie auch, dass Sie vorerst wahrscheinlich `.container` nicht als `body` oder `html`-Element betrachten sollten, aufgrund eines Blink-Bugs. Dieser Bug führt dazu, dass der Blend-Modus auf dem `.mover` ignoriert wird, wenn er animiert wird und `.container` `body` oder `html` ist. Firefox und Safari haben dieses Problem nicht.

In Ordnung, aber das ist nur 2D. Was ist mit unserem Mover, der ein Würfel mit Bildseiten ist, ein Würfel, der sich in 3D dreht?

Sehen Sie den Stift
orbiting cube of pies blending #0
von CSS-Tricks (@css-tricks)
auf CodePen.

Bisher alles gut, aber wir haben noch keine Mischung. Wir setzen `mix-blend-mode: overlay` auf unserem Würfel und... wir haben jetzt Mischung, aber es hat unser 3D kaputt gemacht, die Seiten sind in die Ebene des Würfels abgeflacht!

Sehen Sie den Stift
orbiting cube of pies blending #1
von CSS-Tricks (@css-tricks)
auf CodePen.

Das liegt daran, dass wir 3D-Transformationen auf den Würfel anwenden, während wir ihn animieren, und er hat 3D-transformierte Kinder, also wollen wir, dass unser Würfel den Wert `preserve-3d` für `transform-style` hat. Aber das Setzen von `mix-blend-mode: overlay` auf unserem Würfel zwingt den verwendeten Wert von `transform-style` zu `flat`, so dass die Würfelseiten in die Ebene ihrer Eltern abgeflacht werden. Dies passiert in Firefox nicht, obwohl die Spezifikation sagt, dass es passieren sollte.

Wir könnten versuchen, `mix-blend-mode: overlay` auf den Würfelseiten zu setzen, aber das scheint nicht zu funktionieren. Der Würfel ist abgeflacht und es gibt keine Mischung.

Eine weitere Lösung wäre, ein `.scene`-Element zwischen dem Container und dem beweglichen Würfel hinzuzufügen und `perspective` und `mix-blend-mode` auf diesem Element zu setzen

Sehen Sie den Stift orbiting cube of pies blending #3 von Ana Tudor (@thebabydino) auf CodePen.

Das scheint alles zu reparieren!