Fast jeder, der länger mit CSS arbeitet, kennt diesen Moment: Ein Modal, ein Dropdown oder ein Tooltip soll über allem anderen liegen, doch trotz eines hohen z-index bleibt es teilweise verdeckt. Reflexartig wird der Wert dann auf 9999 oder gleich 999999 gesetzt – und nichts ändert sich. Der Grund ist fast immer derselbe: Nicht der Zahlenwert ist das Problem, sondern der sogenannte Stacking Context, in dem das Element steckt. Wer dieses Konzept einmal verstanden hat, löst solche Überlagerungsprobleme gezielt statt durch Raten. Dieser Artikel erklärt, wann z-index überhaupt greift, was einen neuen Stacking Context erzeugt und wie du systematisch debuggst.
Was z-index eigentlich steuert
Mit z-index legst du die Reihenfolge von Elementen entlang der gedachten Z-Achse fest – also wer vor und wer hinter wem liegt, wenn sich Boxen überlappen. Ein höherer Wert bedeutet weiter vorne, ein niedrigerer weiter hinten. Klingt einfach, hat aber eine zentrale Bedingung: Die Eigenschaft wirkt nicht auf jedes beliebige Element.
Damit z-index überhaupt etwas bewirkt, muss das Element entweder positioniert sein, also einen position-Wert außer static besitzen (relative, absolute, fixed oder sticky), oder es muss ein direktes Kind eines Flex- bzw. Grid-Containers sein. Setzt du z-index auf ein ganz normales static positioniertes Element außerhalb von Flex und Grid, wird der Wert schlicht ignoriert. Das ist die erste Stolperfalle und der Grund, warum manche Regel scheinbar wirkungslos bleibt.
Der Stacking Context: die eigentliche Erklärung
Ein Stacking Context ist eine in sich abgeschlossene Schicht der Stapelreihenfolge. Man kann ihn sich wie eine eigene kleine Welt vorstellen: Innerhalb dieser Welt entscheiden die z-index-Werte der enthaltenen Elemente über ihre Reihenfolge. Nach außen hin verhält sich der gesamte Kontext aber wie ein einziges Element mit einem einzigen Platz im übergeordneten Kontext.
Das ist der Knackpunkt: Ein Kind kann seinen Eltern-Kontext niemals verlassen. Hat dein Overlay einen z-index: 9999, sein Elternelement aber bildet einen Stacking Context mit niedriger Position relativ zu einem Nachbarn, dann landet das Overlay trotzdem hinter diesem Nachbarn. Die 9999 gelten nur innerhalb der eigenen Welt – sie vergleichen sich nicht mit Werten aus anderen Kontexten.
Bildlich gesprochen: Du kannst in deinem Hochhaus im obersten Stockwerk wohnen, doch wenn das ganze Gebäude in einer Senke steht, bist du immer noch tiefer als ein Bungalow auf dem Hügel nebenan. Der z-index regelt nur deine Etage im eigenen Haus, nicht die Höhe des Hauses im Tal.
Was einen neuen Stacking Context erzeugt
Hier wird es für viele überraschend: Längst nicht nur position mit z-index erzeugt einen neuen Kontext. Eine ganze Reihe verbreiteter Eigenschaften tut das ebenfalls – oft unbeabsichtigt. Genau deshalb tauchen die Probleme häufig dort auf, wo niemand sie vermutet: Eine harmlose Animation oder ein Schatten-Effekt kapselt plötzlich das gesamte Overlay ein.
Die folgende Übersicht zeigt die wichtigsten Auslöser und ihre typischen Nebenwirkungen, damit du beim Debuggen weißt, wonach du suchen musst.
| CSS-Eigenschaft / Wert | Erzeugt Kontext, wenn … | Typische Nebenwirkung |
|---|---|---|
position: absolute / relative + z-index (nicht auto) |
z-index einen konkreten Wert hat | Der klassische, meist beabsichtigte Fall |
position: fixed / sticky |
immer (sticky ab Anwendung) | Header oder Sidebar kapseln Kinder unerwartet |
opacity kleiner als 1 |
der Wert < 1 ist | Ein Fade-Effekt sperrt das Overlay ein |
transform (außer none) |
ein Transform gesetzt ist | Selbst translateZ(0) oder Scale wirkt |
filter / backdrop-filter |
ungleich none |
Blur oder Schatten kapseln den Teilbaum |
will-change |
eine relevante Eigenschaft genannt wird | Performance-Hint mit Layout-Nebeneffekt |
isolation: isolate |
gesetzt ist | Bewusstes Werkzeug, sonst nebenwirkungsfrei |
mix-blend-mode (außer normal) |
ein Blend-Modus aktiv ist | Überraschend bei Bildeffekten |
Flex-/Grid-Kind + z-index |
z-index ungleich auto |
Kontext ohne position |
contain: layout / paint / strict |
entsprechend gesetzt | Containment kapselt zusätzlich Stapelung |
Auffällig ist, dass viele dieser Eigenschaften aus ganz anderen Gründen gesetzt werden – für Animationen, Performance oder visuelle Effekte. Niemand setzt opacity: 0.95 mit dem Vorsatz, die Stapelreihenfolge umzubauen. Genau das passiert aber.
Warum z-index: 9999 das Problem oft nicht löst
Wenn du einen astronomisch hohen Wert vergibst und sich nichts ändert, ist das ein fast sicheres Zeichen dafür, dass dein Element in einem Stacking Context gefangen ist, der selbst zu weit hinten liegt. Der Wert kann nicht aus dieser Schicht ausbrechen. Höher zu zählen bringt dann nichts – du erhöhst nur die Etage in einem Haus, das im falschen Tal steht.
Zwei weitere Gründe sorgen für scheinbares Versagen:
- Fehlende Positionierung: Ohne
position(oder Flex-/Grid-Kontext) ignoriert der Browser den Wert komplett. - Wettlauf der hohen Werte: Wenn überall im Projekt
9999steht, gewinnt schlicht das später im DOM stehende Element. Die Inflation der Werte verlagert das Problem, statt es zu lösen.
Die nachhaltige Lösung ist fast nie eine höhere Zahl, sondern das Auflösen oder Verschieben des einkapselnden Kontexts.
Schritt für Schritt debuggen
Statt zu raten, lohnt sich ein methodisches Vorgehen. Die folgende Reihenfolge hat sich in der Praxis bewährt:
- Wirkt z-index überhaupt? Prüfe, ob das Element
positionungleichstatichat oder Flex-/Grid-Kind ist. - Eltern durchgehen: Klicke dich in den DevTools vom Overlay nach oben durch die Vorfahren und suche nach den Eigenschaften aus der Tabelle – besonders
transform,opacity,filterundwill-change. - Kontext identifizieren: Der erste Vorfahr, der einen Stacking Context bildet, ist deine Grenze. Dein Element kann nie höher steigen als dieser Vorfahr im darüberliegenden Kontext.
- Kontext auflösen oder verschieben: Entferne die unnötige Eigenschaft, oder hebe das Overlay im DOM auf eine höhere Ebene (etwa per Portal direkt unter
body). - Bewusst isolieren: Nutze
isolation: isolate, um Kontexte gezielt zu erzeugen, statt sie als Zufallsprodukt zu bekommen.
Viele Browser-DevTools markieren mittlerweile Stacking Contexts oder bieten einen Layer-/3D-Überblick an. Dieser visuelle Blick erspart oft langes Suchen. Wer regelmäßig mit kleinen Code-Snippets oder Berechnungen arbeitet, findet auf den kostenlosen Webtools nützliche Helfer fürs schnelle Ausprobieren.
Saubere Strategien für die Praxis
Damit Überlagerungsprobleme gar nicht erst entstehen, helfen ein paar Grundsätze:
- Wenige, klare Ebenen: Definiere ein kleines Set von z-index-Stufen (z. B. Basis, Dropdown, Sticky-Header, Modal, Toast) als CSS-Variablen statt willkürlicher Zahlen.
- Overlays per Portal: Modals und Tooltips am besten direkt unter
bodyrendern, damit sie keinem fremden Kontext unterliegen. - Bewusst isolieren:
isolation: isolateauf Komponenten-Wurzeln verhindert, dass interne z-index-Werte nach außen lecken. - Effekte hinterfragen: Wenn ein Overlay verschwindet, sobald du eine Animation oder einen Filter hinzufügst, kennst du nun die Ursache.
Mit diesem Denkmodell verlierst du den Respekt vor verschachtelten Layouts. Weitere Beiträge zu Frontend- und Webthemen findest du im News-Bereich oder direkt auf der Startseite.
Häufige Fragen
Warum funktioniert mein z-index nicht?
In den meisten Fällen fehlt entweder eine Positionierung (das Element ist position: static und kein Flex-/Grid-Kind), oder das Element steckt in einem Stacking Context, der selbst zu weit hinten liegt. Prüfe beides, bevor du den Wert erhöhst.
Erzeugt opacity wirklich einen neuen Stacking Context?
Ja. Jeder opacity-Wert kleiner als 1 erzeugt einen neuen Kontext. Das ist eine der häufigsten unbeabsichtigten Ursachen, weil Transparenz oft nur für einen optischen Effekt gesetzt wird.
Hilft ein höherer z-index wie 999999?
Nur innerhalb des eigenen Kontexts. Liegt der umgebende Kontext zu tief, ändert auch ein extrem hoher Wert nichts. Statt höher zu zählen, solltest du den einkapselnden Kontext finden und auflösen oder verschieben.
Wie finde ich heraus, welches Element den Kontext erzeugt?
Gehe in den DevTools vom betroffenen Element schrittweise zu den Vorfahren und achte auf transform, opacity unter 1, filter, will-change, position: fixed/sticky sowie isolation. Der erste Vorfahr mit einer dieser Eigenschaften ist meist die Grenze.
Wirkt z-index auf Flex- und Grid-Elemente ohne position?
Ja. Direkte Kinder eines Flex- oder Grid-Containers reagieren auf z-index auch ohne gesetztes position. Das ist eine der wenigen Ausnahmen von der Positionierungsregel.
Wie vermeide ich z-index-Chaos in großen Projekten?
Lege ein festes, kleines Stufensystem über CSS-Variablen an, rendere Overlays per Portal außerhalb verschachtelter Container und nutze isolation: isolate, um Komponenten-interne Werte zu kapseln. So bleiben die Werte überschaubar und vorhersehbar.