Wahrscheinlich hat fast jeder von uns mindestens einmal in seinem Leben die Z-Index-Eigenschaft verwendet. Darüber hinaus ist sich jeder Entwickler sicher, dass er weiß, wie es funktioniert. Was könnte einfacher sein als Operationen mit ganzen Zahlen (Vergleichen und Zuweisen zu Elementen). Aber ist alles so einfach, wie es auf den ersten Blick scheint?
Vielleicht sind die Informationen, die ich unten behandeln werde, tatsächlich trivial. Ich bin jedoch sicher, dass viele es für sich selbst nützlich finden werden. Diejenigen, die bereits davon wussten, können diesen Text in schwierigen Zeiten als Spickzettel verwenden. Also willkommen bei cat.
Tatsächlich versucht eine Person normalerweise in drei Fällen, ein neues Feld für sich selbst zu sortieren: wenn sie bei der Arbeit unerwartete Ergebnisse erzielt und nicht versteht, was passiert; wenn es notwendig ist, darüber hinauszugehen und das Thema aus einem anderen Blickwinkel zu betrachten; und schließlich nur aus sportlichem Interesse.
Mein Fall gehört eindeutig nicht zur dritten Kategorie. Zuerst bin ich mehrmals in meinem Leben auf das erste Szenario gestoßen, als ich an verschiedenen Projekten gearbeitet habe. Er verstand das Problem jedoch nicht vollständig, da es faul war und es an klaren und verständlichen Materialien mit Beispielen mangelte. Und dann habe ich Anfang dieses Jahres angefangen, eine Web-Engine zu schreiben, die mich dazu brachte, Standards zu lesen und allgemein zu sehen,
wie verschiedene nicht triviale Dinge in gängigen Browsern funktionieren und vor allem,
warum sie so funktionieren.
Beginnen wir mit einem einfachen. Was ist Z-Index und wofür ist es?
Offensichtlich ist dies die Koordinate entlang der Z-Achse, die für ein Element angegeben wurde. Die Z-Achse ist auf den Benutzer gerichtet. Eine größere Anzahl ist ein näheres Element.

Warum sind Z-Index-Zahlen ganzzahlig? Alles ist einfach. Der Bereich ist oben und unten praktisch unbegrenzt, sodass wir keine Bruchwerte verwenden müssen. Da der reale Monitor keine dritte Dimension hat (wir können sie nur simulieren), benötigen wir eine dimensionslose Größe, deren einzige Aufgabe darin besteht, einen Vergleich der Elemente (dh die Reihenfolge der Menge) bereitzustellen. Ganzzahlen leisten bei dieser Aufgabe hervorragende Arbeit, während sie visueller sind als echte.
Es scheint, dass dieses Wissen ausreicht, um Z-Index auf Seiten zu verwenden. Es ist jedoch nicht alles so einfach.
<div style="background: #b3ecf9; z-index: 1"></div> <div style="background: #b3ecb3; margin-top: -86px; margin-left: 38px; z-index: 0"></div>

Etwas scheint schief gelaufen zu sein. Wir haben den ersten Block-Z-Index mehr als den zweiten erstellt. Warum wird er unten angezeigt? Ja, es geht früher durch den Code - aber es scheint, dass dies nur bei gleichen Z-Index-Werten eine Rolle spielen sollte.
An diesem Punkt ist es an der Zeit, den CSS2.1-Standard bzw. dessen Anwendung für die Verarbeitung von Overlay-Kontexten zu öffnen. Hier ist der
Link .
Aus diesem kleinen und sehr prägnanten Text können Sie sofort viele wichtige Informationen extrahieren.
- Überlagerung der Z-Index-Steuerung nicht über einzelne Elemente, sondern überlagert Kontexte (Elementgruppen)
- Wir können Elemente in unterschiedlichen Kontexten nicht willkürlich relativ zueinander steuern: Hier funktioniert die Hierarchie. Wenn wir uns bereits in einem „niedrigen“ Kontext befinden, können wir ihn nicht zu einem Element über dem Element eines „höheren“ Kontexts machen.
- Der z-Index ist für Elemente in einem normalen Stream (für den die Positionseigenschaft statisch ist) überhaupt nicht sinnvoll. Wir sind im obigen Beispiel in diese Falle geraten.
- Damit ein Element einen neuen Überlagerungskontext definieren kann, muss es positioniert und ein Z-Index zugewiesen werden.
- Wenn das Element positioniert ist, der Z-Index jedoch nicht festgelegt ist, können wir bedingt annehmen, dass er gleich Null ist (in einfachen Fällen funktioniert dies so, wir werden die Nuancen später betrachten).
- Einzelne Überlagerungskontexte werden durch Elemente mit einem Deckkraftwert von weniger als eins festgelegt. Dies wurde durchgeführt, damit Sie die Alpha-Mischung problemlos in die letzte Stufe des Renderns übertragen können, um sie von der Grafikkarte zu verarbeiten.
Das ist aber noch nicht alles. Es stellt sich heraus, dass es mit Elementen ohne Z-Index auch nicht so einfach ist, wie es scheint.
Das Rendern von Elementen des Kontext-Teilbaums kann in mehrere Phasen unterteilt werden (von denen die ersten beiden direkt die Hintergrundfarbe und das Hintergrundbild des aktuellen Elements ausgeben, das den Kontext festlegt).
Betrachten Sie also die gesamte Liste.
3. Ableitung von untergeordneten Kontexten mit negativem Z-Index
4. Ausgabe von untergeordneten Blockelementen in einem normalen Ablauf (nur Hintergründe)
5. Ausgabe von untergeordneten Float-Elementen
6. Die Ausgabe des Inhalts von Elementen in einem normalen Stream: Inline- und Inline-Block-Nachkommen, Inline-Inhalt innerhalb von Block-Nachkommen, einschließlich Textzeilen *
7. Die Ausgabe von untergeordneten Kontexten mit Null und automatischem Z-Index **
8. Ableitung von untergeordneten Kontexten mit positivem Z-Index
* um den Tiefenbaum zu durchqueren
** Betrachten Sie für Kontexte mit z-index: auto alle untergeordneten Kontexte als Nachkommen des aktuellen Kontexts, dh ziehen Sie sie auf die aktuelle Ebene
Schon nicht so einfach, oder? Sie können dieses Schema anhand des folgenden Bildes grob veranschaulichen:

Es ist auch möglich, ein Beispiel für einen
Codepen zu öffnen und mit Ihren eigenen Händen damit zu spielen.
Das ist aber noch nicht alles. Es scheint, dass der Algorithmus bereits ziemlich kompliziert ist: Wir müssen zuerst die untergeordneten Kontexte innerhalb der Pseudokontexte aufrufen (erinnern Sie sich an den Wert auto?), Dann nach zwei Z-Index-Listen sortieren, sie in einer Zahlenreihe anordnen und dann die untergeordneten durchgehen: zuerst blockieren in einem normalen Stream, dann schwebend, dann Inline und Inline-Block ...
Aber hier warten wir auf zwei Überraschungen. Der erste wird uns mit etwas Glück nicht betreffen. Dies hängt damit zusammen, dass der Hintergrund mit Frames und der Inhalt der Blockelemente in verschiedenen Phasen angezeigt werden. Wenn jedoch unsere selbst erstellte Engine für jeden Textknoten ein automatisch inline Element erstellt, ist alles in Ordnung, und sie werden natürlich später angezeigt.
Aber der zweite ist nicht so trivial. Es ist markiert
Behandeln Sie das Element für jedes dieser Elemente so, als ob es einen neuen Stapelkontext erstellt hätte. Alle positionierten Nachkommen und Nachkommen, die tatsächlich einen neuen Stapelkontext erstellen, sollten jedoch als Teil des übergeordneten Stapelkontexts betrachtet werden, nicht als Teil dieses neuen.
float- und inline-block / inline-Elemente (aber nicht block!).
Was bedeutet das in der Praxis? Und das bedeutet, dass wir sie genauso verarbeiten müssen wie Elemente mit z-index: auto. Das heißt, zuerst gehen Sie um ihre Teilbäume herum und ziehen von dort aus untergeordnete Kontexte heraus, um sie auf die aktuelle Ebene zu bringen. Im Übrigen sollten wir sie als Elemente behandeln, die unseren Kontext definieren.
Dies bedeutet, dass alle Teilbäume in ihnen, die nach dem Crawlen in eine lineare Liste gestreckt werden, atomar bleiben sollten. Mit anderen Worten, wir können die Reihenfolge der Elemente nicht so mischen, dass die Nachkommen eines solchen Elements über ihrem übergeordneten Element „schweben“. Und wenn es für untergeordnete Kontexte intuitiv klar ist (weil der Algorithmus rekursiv ist), dann ist es hier nicht so.
Daher müssen wir uns beim Schreiben des Engine-Codes so betrügen, dass die Elemente float, inline und inline-block vorerst ihre Nachkommen nicht preisgeben (mit Ausnahme von untergeordneten Elementen mit Positionierung und Z-Index, die Overlay-Kontexte bilden) und dann für sie ausgeführt werden Die gesamte Funktion ist rekursiv, im Gegenteil, unter Berücksichtigung der Tatsache, dass untergeordnete Kontexte während einer Durchquerung übersprungen werden sollten.
Einige Beispiele zur Demonstration dieses Phänomens:
<div style="float: left; background: #b3ecf9;"> <div style="width: 40px; height: 40px; background: #fff700; position: relative; z-index: -1; top: -20px; left: -20px;"></div> </div>

Hier hat das Kind einen Z-Index und ist positioniert. Es wird angezeigt, aber unter einem blauen Quadrat angezeigt, da Elemente mit negativem Z-Index in Stufe 3 und Float-Elemente in Stufe 5 angezeigt werden.
<div style="float: left; margin-top: -30px; background: #b3ecf9;"> <div style="width: 40px; height: 40px; background: #fff700; position: relative; z-index: 0;"></div> </div> <div style="background: #b3ecb3; margin-top: 52px; margin-left: 38px;"> <div style="width: 40px; height: 40px; background: #ff0000; position: relative; z-index: 0;"></div> </div>

In diesem Beispiel wird das zweite Element (grün) vor dem ersten (blau) und daher unten angezeigt. Die Kinder werden jedoch hochgezogen (weil sie ihre eigenen Kontexte festlegen). In diesem Fall gehen sie also in derselben Reihenfolge vor, in der sie genau in den ursprünglichen Baum passen (die Reihenfolge ihrer Vorfahren nach der Permutation ist nicht wichtig!). Wenn wir das erste Kind auf den Z-Index gleich 1 setzen, erhalten wir das folgende Bild:

Fügen Sie weitere Elemente hinzu.
<div style="float: left; background: #b3ecf9;"> <div style="float: left"> <div style="width: 40px; height: 40px; background: #fff700; position: relative; z-index: 0;"></div> </div> </div> <div style=" background: #b3ecb3; margin-top: 32px; margin-left: 40px;"> <div style="position: relative"> <div style="width: 40px; height: 40px; background: #ff0000; position: relative; z-index: 0;"></div> </div> </div>

Hier werden untergeordnete Kontexte sowohl aus Floats als auch aus gewöhnlichen Blöcken gezogen, während die Reihenfolge wie im ursprünglichen Baum beibehalten wird.
Zum Schluss das letzte Beispiel:
<div style="background: #b3ecf9;"> <div style="display: inline-block; width: 40px; height: 40px; background: #fc0;"></div> </div> <div style="background: #b3ecb3; margin-top: -100px; margin-left: 22px;"></div>

Wie Sie sehen können, ist das „Herausspringen“ eines Blockelements im Gegensatz zu anderen Fällen durchaus möglich, und da ein Inline-Blockelement auftaucht, ist es das letzte in diesem Dokument.
Wie Sie sehen können, können Sie mit dem Z-Index viele interessante Tricks ausführen (was es zumindest wert ist, das Element unter seinem unmittelbaren übergeordneten Element mit einem negativen Z-Index für das untergeordnete Element auszublenden). Ich hoffe, dieser Artikel hat Ihnen geholfen.