Das Problem
Eine Pricing-Card ist per transform: scale(1.05) leicht vergrößert dargestellt – ein klassischer Effekt um die empfohlene Option hervorzuheben. Alles sieht gut aus, bis man weiter scrollt: Der Abschnitt direkt darunter wird von der Card überlappt.
.pricing-card--featured {
transform: scale(1.05);
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2);
}
Die Card ragt visuell in den nächsten Abschnitt hinein. Was jetzt?
Diagnose 1 (falsch): “Das ist ein Padding-Problem”
Gedanke: Der Container hat zu wenig Platz unten. Mehr Padding macht Luft.
.pricing-grid {
padding-bottom: 2rem;
}
Ergebnis: Keine Wirkung. Die Überlappung bleibt.
Warum das nicht funktioniert: padding-bottom fügt Platz innerhalb des Containers hinzu. Aber das Problem ist nicht, dass der Container zu klein ist – transform: scale() verändert die visuelle Größe des Elements, ohne den DOM-Flow zu beeinflussen. Der Browser reserviert für die Card immer noch genau den gleichen Platz wie ohne Transform. Der Container weiß gar nicht, dass die Card optisch herausragt.
Diagnose 2 (falsch): “Das ist ein Stacking-Problem”
Gedanke: Die Card liegt über dem nächsten Abschnitt, weil der Stacking Context falsch ist. Mit z-index kann man das regeln.
.folgeauftrag {
position: relative;
z-index: 2;
}
Ergebnis: Der Text des nächsten Abschnitts wird jetzt sichtbar durch die Card gerendert – also über ihr. Die physische Überlappung bleibt trotzdem bestehen.
Das macht die Sache sogar schlimmer: Jetzt überlagern sich Card und Abschnitts-Inhalt visuell, aber keiner von beiden weicht zurück.
Warum das nicht funktioniert: z-index steuert die Render-Reihenfolge, nicht den physischen Platz im Layout. Das Element wird zwar über der Card gerendert, aber es nimmt immer noch denselben Platz im DOM ein wie vorher. Es gibt keine Kollisionsvermeidung – die beiden Elemente teilen sich denselben Bildschirmbereich, nur wer oben gerendert wird ändert sich.
Diagnose 3 (richtig): “Das ist ein Layout-Abstandsproblem”
Gedanke: Wenn transform: scale() den DOM-Flow nicht verändert, muss der nötige Abstand explizit geschaffen werden. Nicht durch Padding (innen), sondern durch Margin (außen).
.pricing-grid {
margin-bottom: 5rem;
}
Ergebnis: Die Überlappung ist weg. Der nächste Abschnitt beginnt mit ausreichend Abstand.
Die Ursache: Was transform:scale() wirklich macht
transform: scale(1.05) ist eine rein visuelle Operation. Der Browser rendert das Element 5% größer, aber im Dokument-Layout bleibt der Platz für das Element unverändert.
Konkret bedeutet das:
- Der Grid-Container berechnet seine Höhe ohne den Scale-Effekt
- Die skalierte Card ragt visuell über den Container hinaus
- Der
box-shadow: 0 15px 40pxverstärkt diesen Effekt noch – der Schatten hat ebenfalls keinen Einfluss auf den DOM-Flow - Der nächste Abschnitt beginnt direkt unterhalb des unveränderten Containers
┌──────────────────────────────────┐
│ Pricing Grid (DOM-Größe) │
│ │
│ ┌────┐ ┌──────────┐ ┌────┐ │
│ │Card│ │ Card │ │Card│ │
│ │ │ │ featured │ │ │ │
│ └────┘ └──────────┘ └────┘ │
└──────────────────────────────────┘
╔════════════╗ ← visuell
║ scale(1.05)║ herausragend
╚════════════╝
┌──────────────────────────────────┐
│ Nächster Abschnitt │ ← beginnt hier (DOM)
│ ...wird überlappt... │
└──────────────────────────────────┘
Das margin-bottom auf dem Grid verschiebt den Startpunkt des nächsten Abschnitts nach unten. Genug, um den visuellen Überhang (Scale + Shadow) aufzufangen.
Warum zuerst z-index probiert wird (und warum es falsch ist)
“Etwas überlappt etwas anderes” klingt intuitiv nach einem Stacking-Problem. Aber Stacking-Probleme entstehen wenn Elemente absichtlich übereinandergelegt werden (z.B. Overlays, Modals, Dropdowns). Dann regelt z-index wer oben liegt.
Bei Transform-Overlaps ist das anders: Die Elemente sollen gar nicht übereinanderliegen. Eines soll unter dem anderen stehen, aber der visuelle Effekt des ersten ragt in das zweite hinein. Hier hilft kein z-index – hier fehlt Abstand.
Faustregel:
- Element liegt absichtlich über einem anderen? →
z-index - Element nimmt zu viel visuellen Platz ein? →
marginoderpadding transform: scale()beteiligt? → Fast immermargin
Lessons Learned
transform: scale()ist unsichtbar für den Layout-Engine. Es verändert nie den Platz im DOM-Flow. Alle Folge-Elemente positionieren sich so, als wäre der Scale nicht vorhanden.box-shadowist ebenfalls unsichtbar für den Layout-Engine. Ein großer Schatten ragt visuell weit heraus, nimmt aber keinen Platz ein. Bei skalierten Elementen mit Schatten braucht man doppelt so viel margin-Puffer.z-index ist die falsche Werkzeugkiste für Abstandsprobleme. Wenn die Frage ist “warum überlappt das?”, kommt z-index erst infrage wenn die Antwort auf “haben diese Elemente genug Abstand?” bereits “Ja” ist.
Debuggen mit DevTools: Im Browser-Inspector kann man
transform: nonetemporär auf dem Element setzen. Wenn das Element dann nicht mehr überlappt – isttransformdie Ursache undmarginist die Lösung. Wenn es trotzdem überlappt – stimmt etwas anderes nicht.
Quick-Reference
| Symptom | Ursache | Fix |
|---|---|---|
transform:scale() Element überlappt nächsten Abschnitt | DOM-Flow ignoriert scale | margin-bottom auf Element oder Container |
| z-index macht Text “durchsichtig” sichtbar | Stacking Order geändert, nicht Platz | z-index rückgängig, stattdessen margin |
padding-bottom auf Container hat keine Wirkung | Element ragt aus Container heraus | margin-bottom auf Container statt padding |
| Überlappung bleibt trotz viel Platz | Shadow ragt weiter als das Element | margin-bottom um shadow-blur-radius erhöhen |