Demonstrationen und Beispiele für stacking-order, stacking-level, stacking-context und z-index-Vergabe

In allen hier demonstrierten Fällen wird der erste Container, der schwarze, den stacking-context aufmachen, gehört also zu Level 1 (s.o.).
Zu diesem Zweck wurde ihm position: relative; und z-index: 0; gegeben.
Dies dient zur besseren Verdeutlichung damit nicht <body> oder <html> den stacking-context bilden, was etwas unanschaulich zur erklären wäre.

Keines der divs ist positioniert und sie sind ineinander verschachtelt.
Alle divs sind Level 3. (s.o.) ausser dem schwarzen div (Level 1).
Kein z-index wurde vergeben.
Jedes div ist z-über dem vorhergehenden aufgrund der General Regel.

Zeige Code

HTML:
<div class="first">
 <div class="second">
  <div class="third">
   <div class="fourth">
    <div class="fifth">
     <div class="sixth">
      <div class="seventh">
      </div>
     </div>
    </div>
   </div>
  </div>
 </div>
</div>
CSS:
.first {
 padding: 10px;
 width: 400px;
 height: 300px;
 background: #000;
 position: relative;
 z-index: 0;
/* bildet stacking-context */
}
.second {
 padding: 10px;
 width: 380px;
 height: 280px;
 background: #397A30;
}
.third {
 padding: 10px;
 width: 360px;
 height: 260px;
 background: #9E9A2F;
}
.fourth {
 padding: 10px;
 width: 340px;
 height: 240px;
 background: #AD2D3D;
}
.fifth {
 padding: 10px;
 width: 320px;
 height: 220px;
 background: #555579;
}
.sixth {
 padding: 10px;
 width: 300px;
 height: 200px;
 background: #838383;
}
.seventh {
 padding: 10px;
 width: 280px;
 height: 180px;
 background: #FFF;
}

Keines der divs ist positioniert.
Alle divs sind Level 3. (s.o.) ausser dem schwarzen (Level 1).
Kein z-index wurde vergeben.
Jedes div ist y-unter dem vorhergehenden ausser dem ersten welches alle beherbergt.

Zeige Code

HTML:
<div class="first">
 <div class="second">
 </div>
 <div class="third">
 </div>
 <div class="fourth">
 </div>
 <div class="fifth">
 </div>
 <div class="sixth>>
 </div>
 <div class="seventh">
 </div>
</div>
CSS:
.first {
 padding: 10px;
 width: 400px;
 height: 300px;
 background: #000;
 position: relative;
 z-index: 0;
/* bildet stacking-context */
}

.second {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #397A30;
}
.third {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #9E9A2F;
}
.fourth {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #AD2D3D;
}
.fifth {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #555579;
}
.sixth {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #838383;
}
.seventh {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #FFF;
}

In beiden Beispielen haben wir die natürliche stacking-order demonstriert, also die Ordnung nach der General Regel.
Kein Element wurde positioniert und es wurde kein z-index vergeben.
Das schwarze div hat Level 1., die anderen alle Level 3.


Alles ist wie oben links, nur dass wir dem vierten div, dem roten, eine negative margin gegeben haben.
So haben wir demonstriert, dass auch wirklich jeder im Quellcode folgende container z-über dem vorhergehenden liegt, wie Sie an der Überlappung oben sehen können.

Zeige Code

HTML:
<div class="first">
 <div class="second">
  <div class="third">
   <div class="fourth">
    <div class="fifth">
     <div class="sixth">
      <div class="seventh">
      </div>
     </div>
    </div>
   </div>
  </div>
 </div>
</div>
CSS:
.first {
 padding: 10px;
 width: 400px;
 height: 300px;
 background: #000;
 position: relative;
 z-index: 0;
/* bildet stacking-context */
}
.second {
 padding: 10px;
 width: 380px;
 height: 280px;
 background: #397A30;
}
.third {
 padding: 10px;
 width: 360px;
 height: 260px;
 background: #9E9A2F;
}
.fourth {
 padding: 10px;
 width: 340px;
 height: 240px;
 background: #AD2D3D;
 margin-top: -13px;
}
.fifth {
 padding: 10px;
 width: 320px;
 height: 220px;
 background: #555579;
}
.sixth {
 padding: 10px;
 width: 300px;
 height: 200px;
 background: #838383;
}
.seventh {
 padding: 10px;
 width: 280px;
 height: 180px;
 background: #FFF;
}

Hier ist alles wie oben rechts. Wir haben allerdings dem fünften div, dem violetten, eine negative margin gegeben.
Gleichzeitig haben wir es in der width etwas verkleinert um die Überlappung deutlicher zu machen.

Zeige Code

HTML:
<div class="first">
 <div class="second">
 </div>
 <div class="third">
 </div>
 <div class="fourth">
 </div>
 <div class="fifth">
 </div>
 <div class="sixth>>
 </div>
 <div class="seventh">
 </div>
</div>
CSS:
.first {
 padding: 10px;
 width: 400px;
 height: 300px;
 background: #000;
 position: relative;
 z-index: 0;
/* bildet stacking-context */
}

.second {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #397A30;
}
.third {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #9E9A2F;
}
.fourth {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #AD2D3D;
}
.fifth {
 padding: 10px;
 width: 340px;
 height: 30px;
 background: #555579;
 margin-top: -15px;
}
.sixth {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #838383;
}
.seventh {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #FFF;
}

Auch in den letzten beiden Beispielen ist die natürliche stacking-order nach der General Regel demonstriert worden.
Die Überlappungen sollen die stacking-order deutlich machen.
Das schwarze div hat Level 1., die anderen alle Level 3.


Schauen wir einmal was passiert, wenn wir einem der Container einen Level 2. geben, also ihn poistionieren und ihm einen negativen z-index geben.

Irgendein Text befindet sich hier, blablabla, blablabla
Und noch mehr Text befindet sich hier, blablabla, blablabla
Zeile drei des blablabla-Texts.

Zeige Code

HTML:
<div class="first">
 <div class="second">
  <div class="third">
   <div class="fourth">
    <div class="fifth">
     <div class="sixth">
      <div class="seventh">
      </div>
     </div>
    </div>
   </div>
  </div>
 </div>
</div>
CSS:
.first {
 padding: 10px;
 width: 400px;
 height: 300px;
 background: #000;
 position: relative;
 z-index: 0;
/* bildet stacking-context */
}
.second {
 padding: 10px;
 width: 280px;
 height: 280px;
 background: #397A30;
}
.third {
 padding: 10px;
 width: 260px;
 height: 260px;
 background: #9E9A2F;
}
.fourth {
 padding: 10px;
 width: 240px;
 height: 240px;
 background: #AD2D3D;
}
.fifth {
 padding: 10px;
 width: 220px;
 height: 220px;
 background: #555579;
}
.sixth {
 padding: 10px;
 width: 300px;
 height: 200px;
 background: #838383;
 position: relative;
 z-index: -1;
}
.seventh {
 padding: 10px;
 width: 280px;
 height: 180px;
 background: #FFF;
}

Links haben wir nun dem sechsten div, dem grauen, eine position: relative; und einen z-index: -1; gegeben.
Gleichzeitig haben wir die vorherigen div in der width verkleinert, um das nun nach z-hinten gewanderte div sichtbar zu machen.
Unser sechster Container hat also nun Level 2.
Natürlich befinden sich die anderen Container (ausser dem schwarzen, welcher ja das Elternelement ist welches den stacking-contextbildet) über dem grauen
und das obwohl sie doch Elternelemente des grauen sind.

Erklärung s.u.

Zeige Code

HTML:
<div class="first">
 <div class="second">
 </div>
 <div class="third">
 </div>
 <div class="fourth">
 </div>
 <div class="fifth">
 </div>
 <div class="sixth>>
 </div>
 <div class="seventh">
 </div>
</div>
CSS:
.first {
 padding: 10px;
 width: 400px;
 height: 300px;
 background: #000;
 position: relative;
 z-index: 0;
/* bildet stacking-context */
}

.second {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #397A30;
}
.third {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #9E9A2F;
}
.fourth {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #AD2D3D;
}
.fifth {
 padding: 10px;
 width: 320px;
 height: 30px;
 background: #555579;
 opacity: .8;
}
.sixth {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #838383;
 margin-top: -10px;
 position: relative;
 z-index: -1;
}
.seventh {
 padding: 10px;
 width: 320px;
 height: 30px;
 background: #FFF;
 margin-top: -10px;
 opacity: .8;
}

Rechts haben wir ebenfalls dem sechsten div, dem grauen, eine position: relative; und einen z-index: -1; gegeben.
Gleichzeitig haben wir, um das Ergebnis besser sichtbar zu machen, ihm eine negative margin gegeben.
Dem vorhergehenden div, dem violetten, und auch dem nachfolgenden, dem weißen, haben wir eine opacity: .8; vergeben, um den dahinterliegenden grauen Container besser sichtbar zu machen. Dem weißen div haben wir ebenfalls eine negative margin gegeben.
! Der IE7 hat opacity noch nicht implementiert und zeigt das Durchscheinen somit nicht.

Wir können hier wunderbar sehen, daß wir die natürliche stacking-order nach der General Regel aushebeln können wenn wir Elementen andere Level aufzwingen (Hier Level 2. für das graue div).
Zeigen wir das einmal an einem Beispiel, welches die stacking-order mit allen Leveln demonstriert:


Hier befindet sich ein Text, mal sehen ob der sichtbar wird...

Zeige Code

HTML:
<div class="first">
 <div class="second">
  <div class="third">
   <div class="fourth">
    <div class="fifth">
     <div class="sixth">
      <div class="seventh">
      </div>
     </div>
    </div>
   </div>
  </div>
 </div>
</div>
CSS:
.first {
 padding: 10px;
 width: 400px;
 height: 300px;
 background: #000;
 position: relative;
 z-index: 0;
/* bildet stacking-context */
}
.second {
 padding: 10px;
 width: 290px;
 height: 280px;
 background: #397A30;
 position: relative;
 z-index: 1;
/* neuer st.-context */
}
.third {
 padding: 10px;
 width: 260px;
 height: 260px;
 background: #9E9A2F;
 position: relative;
}
.fourth {
 padding: 10px;
 width: 240px;
 height: 240px;
 background: #AD2D3D;
 float: left;
}
.fifth {
 padding: 10px;
 width: 210px;
 height: 220px;
 background: #555579;
}
.sixth {
 padding: 10px;
 width: 300px;
 height: 200px;
 background: #838383;
 position: relative;
 z-index: -1;
/* n. st.-cont. */
}
.seventh {
 padding: 10px;
 width: 280px;
 height: 180px;
 background: #FFF;
}

Links haben wir versucht alle möglichen Level darzustellen (schauen sie in den Code).
Der sechste Container, der graue, hat position: relative; z-index: -1; verpasst bekommen.
Er wird z-unter den Containern drei, vier und fünf dargestellt, weil erstgenannter nun Level 2. hat, die anderen aber Level 3.
Der zweite, der grüne Container, bleibt z-unter dem grauen, da das grüne div positioniert ist und einen positiven z-index hat und somit einen neuen stacking-context für seine Kindelemente aufmacht, also für den gelben Container und dessen Kindelemente.
Zwar hat der grüne Container nun Level 7., müsste also z-über allen anderen Levels liegen, die folgenden Container sind aber ja Kindelemente des grünen und somit an seinen stacking-context gebunden. D.h. in Wahrheit hat der gelbe Container zwar Level 6. (weniger als der grüne mit Level 7.), dies aber ja im stacking-context des grünen und nicht im ursprünglichen schwarzen.
Dem vierten, dem roten, Container haben wir ein float: left; verpasst (Level 4.). Warum überdeckt er trotzdem nicht Container fünf (violett), welcher ja Level 3. hat (normales Block-Element im normalen Fluss, ohne Positionierung und ohne z-index) ?
Ganz einfach: Container fünf (violett) ist ein Kindelement von Container vier (rot) und floated als Inhalt des roten Containers mit, ist also gar nicht Level 3., weil er nicht mehr im normalen Fluss steht (gefloatete Elemente stehen ja ausserhalb des normalen Flusses).
Was ist denn eigentlich mit dem gelben div ?
Das hat doch Level 6. innerhalb des neu gebildeten grünen stacking-context.
Warum wird erstgenanntes dann nicht über dem roten mit Level 4. angezeigt ?
Nun, der rote Container ist ja ein Kindelement des gelben und somit ja indirekt positioniert.
Nicht dass position: relative; automatisch vererbar wäre, also dass das rote div nun auch positioniert wäre, aber als Kindelement des gelben kann es ja aus dessen Positionierung nicht entkommen, es sei denn es würde seinerseits positioniert. Der rote Container ist also eigentlich gar nicht nicht Level 4., weil er durch sein Elternelement indirekt eben doch positioniert ist.
Verwirrend ?
Wir müssen beim Betrachten der stacking-order nach unseren Regeln (s.o.) also auch immer beachten, ob zwischendurch
1. ein neuer stacking-context aufgemacht wurde und
2. ob der von uns bestimmte Level auch wirklich stimmt, was bei Kindes-Kindelementen mit Bedacht beurteilt werden muß.
Im rechten Beispiel kann man sehen was, bei gleichen CSS-Eigenschaften wie im vorliegenden Beispiel, passiert, wenn die Container nicht Kindelemente voneinander sind sondern y-untereinander dargestellt werden.

Zeige Code

HTML:
<div class="first">
 <div class="second">
 </div>
 <div class="third">
 </div>
 <div class="fourth">
 </div>
 <div class="fifth">
 </div>
 <div class="sixth>>
 </div>
 <div class="seventh">
 </div>
</div>
CSS:
.first {
 padding: 10px;
 width: 400px;
 height: 300px;
 background: #000;
 position: relative;
 z-index: 0;
/* bildet stacking-context */
}

.second {
 padding: 10px;
 width: 300px;
 height: 30px;
 background: #397A30;
 position: relative;
 z-index: 1;
}
.third {
 padding: 10px;
 width: 320px;
 height: 30px;
 background: #9E9A2F;
 margin-top: -13px;
 position: relative;
}
.fourth {
 padding: 10px;
 width: 340px;
 height: 30px;
 background: #AD2D3D;
 margin: -13px 0 -13px 0;
 float: left;
}
.fifth {
 padding: 10px;
 width: 360px;
 height: 30px;
 background: #555579;
 clear: left;
}
.sixth {
 padding: 10px;
 width: 380px;
 height: 30px;
 background: #838383;
 margin-top: -13px;
 position relative;
 z-index: -1;
}
.seventh {
 padding: 10px;
 width: 360px;
 height: 30px;
 background: #FFF;
 margin-top: -13px;
}

Rechts haben wir die gleichen Eigenschaften auf die verschiedenen div verteilt wie links.
Hier allerdings sind die Container ja nicht ineinander verschachtelt sondern stehen y-untereinander.
Sogleich haben unsere vergebenen Eigenschaften einen starken Effekt. Wir haben die komplette natürliche Ordnung umgeworfen. Kein div sitzt mehr auf der z-Achse in der Reihenfolge des Vorkommens im Quelltext.
Um dies sichtbar zu machen haben wir einige negative margin vergeben damit die div sich überlappen.
Folgend die Level-Verteilung:
schwarz: Level 1. (bildet stacking-context
grün: Level 7. (positioniert und z-index: 1;
gelb: Level 6. (positioniert)
rot: Level 4. (float: left;)
violett: Level 3. (block-level-element in normalem Fluss)
grau: Level 2. (positioniert und z-index: -1;
weiß: Level 3. (block-level-element in normalem Fluss)
Was Level 5. betrifft (inline-elements im normalen Fluss), haben wir diese hier nicht aufgeführt, da das Verhalten von diesen Elementen stark davon abhängt in welchem elternelement sie sich befinden (meist ja ein Level 3. Element (z.B. <p>).
Wir wissen aber ja, dass Text und Bilder immer z-über ihrem Elternelement sitzen (anders wäre es sicher auch nicht sinnvoll ;-) ) und es ist leicht nachzuvollziehen, dass in einem stacking-context Elemente mit höherem Level beispielsweise Text überdecken.
Siehe dazu auch die Abhandlung über reine CSS-Tooltips.
In der Abhandlung über CSS-Tooltips kommt zum Tragen, dass jedes inline-element auch zu einem block-level-element gemacht werden kann. Zum einen mit display: block; und zum anderen durch Positionierung. Positionierung macht ein Element ja auch zu einem Block-Element. Der stacking-context und die z-index-Eigenschaft sind bei den CSS-Tooltips von grosser Bedeutung.

IE7 hat hier einen seiner vielen Bugs.
Das vierte div, das rote, hat die Eigenschaft float: left; und das fünfte, das violette clear: left; um es y-unter dem roten darzustellen.
Das rote div hat folglich Level 4. und das violette nur Level 3.
Trotzdem stellt IE7 das violette div z-über dem roten dar, was verkehrt ist.

Es dürfte klar sein, daß, würden in obigem Beispiel alle Container auf einer y-Ebene liegen, sie in der z-Reihenfolge Ihres Levels nach am Anfang aufgeführten Regel dargestellt werden müssten, was wir hier durch lediglich leichte Überlappung demonstriert haben.

Die Beispiele lassen sich teilweise schwerlich auf dem zweidimensionalen Bildschirm darstellen und wir können hier nicht alle erdenklichen Konstellationen demonstrieren. Zum Schluss aber noch ein interaktives Beispiel:


Level 7.

Level 6.

Level 4.

Level 3.

» margin-top: 0;

--- Level 6. ---

Das weiße div mit blauem Rand ist ein Kindelement des violetten div.
Es ist positioniert und erlangt somit Level 6.

» margin-top: -20px;

--- Level 6. ---

Lediglich mit negativen margins wird das div nun verschoben und wir sehen, dass es alle divs mit niedrigerem Level überlagert.
Wir erinnern uns, das rote div ist gefloated, also Level 4.

» margin-top: -40px;

--- Level 6. ---

Das schwarze div bildet ohnehin den stacking-context und gehört somit zu Level 1., wird also auch überlagert.

» margin-top: -65px;

--- Level 6. ---

Das gelbe div hat ebenfalls Level 6. (positioniert), es wird jedoch durch unser weißes div überlagert, da dieses im Quelltext später steht (siehe General Regel).

» margin-top: -90px;

--- Level 6. ---

Das grüne div ist positioniert und hat z-index: 1; womit es Level 7. hat. Somit muß sich unser div "fügen" und wird von dem grünen verdeckt.

Level 2.

Level 3.

Zeige Code

HTML:
<div class="first">
 <div class="second">
 </div>
 <div class="third">
 </div>
 <div class="fourth">
 </div>
 <div class="fifth">
  <div></div>
 </div>
 <div class="sixth>>
 </div>
 <div class="seventh">
 </div>
</div>
CSS:
.first {
 padding: 10px;
 width: 400px;
 height: 300px;
 background: #000;
 position: relative;
 z-index: 0;
/* bildet stacking-context */
}

.second {
 padding: 10px;
 width: 270px;
 height: 30px;
 background: #397A30;
 position: relative;
 z-index: 1;
}
.third {
 padding: 10px;
 width: 290px;
 height: 30px;
 background: #9E9A2F;
 margin-top: -13px;
 position: relative;
}
.fourth {
 padding: 10px;
 width: 310px;
 height: 30px;
 background: #AD2D3D;
 margin: -13px 0 -13px 0;
 float: left;
}
.fifth {
 padding: 10px;
 width: 340px;
 height: 30px;
 background: #555579;
 clear: left;
}
.fifth div {
 position: relative;
 width: 120px;
 height: 22px;
 border: 4px solid #0053FA;
 left: 222px;
}
.sixth {
 padding: 10px;
 width: 350px;
 height: 30px;
 background: #838383;
 margin-top: -13px;
 position relative;
 z-index: -1;
}
.seventh {
 padding: 10px;
 width: 330px;
 height: 30px;
 background: #FFF;
 margin-top: -13px;
}

Die interaktive Demonstration wurde nur mit CSS entwickelt.

Mit dem Fehler im IE7, der das violette div (Level 3.) über dem roten div (Level 4.) darstellt, habe ich mich nicht weiter befasst.
Wenn jemand einen Tip hat, ist er willkommen.


Ich hoffe meine Ausführungen waren nicht allzu chaotisch und Sie konnten etwas an Erkenntnis mitnehmen.