Schalte ein Element in einer scrollenden Demo zwischen static, relative, absolute, fixed und sticky um. Containing Blocks, inset, Fehlersuche bei sticky und Zentrieren verständlich erklärt.
Die Eigenschaft position legt fest, wie ein Element platziert wird. static ist der normale Fluss. relative verschiebt es leicht und behält seinen Platz. absolute nimmt es aus dem Fluss und platziert es relativ zum nächsten positionierten Vorfahren. fixed heftet es an den Viewport. sticky scrollt normal, bis es einen Schwellenwert wie top: 0 erreicht, und bleibt dann dort stehen.
Die fünf Werte
Wert
Im Fluss?
Platziert relativ zu
Bleibt im Fluss
Nichts, top/left haben keine Wirkung
Bleibt im Fluss, sein ursprünglicher Platz bleibt erhalten
Seiner eigenen normalen Position
Aus dem Fluss genommen
Der Padding-Box des nächsten positionierten Vorfahren
Aus dem Fluss genommen
Dem Viewport, außer ein Vorfahre hat transform, filter oder Ähnliches
Bleibt im Fluss
Dem nächsten scrollenden Vorfahren, innerhalb seines Elternelements
Die Demo unten enthält eine orange Box in einem scrollbaren Bereich. Wechsle ihren position-Wert, verschiebe die Offsets, scrolle und beobachte, wovon aus sie gemessen wird. Danach folgen ein Leitfaden zu Containing Blocks, eine Checkliste für sticky, das nicht kleben will, und die Kurzschreibweise inset.
Wähle einen position-Wert für die orange Box.
Lege top und left fest und schalte das positionierte Elternelement ein oder aus, um zu sehen, welche Box absolute verwendet.
Scrolle in der Demo, um fixed und sticky zu vergleichen.
Kopiere das CSS, das zu dem passt, was du siehst.
Setze position: relative auf eine Karte, dann nutzen absolute Kindelemente diese Karte als Rahmen. Dieses eine Muster deckt die meisten Layouts mit Badges und Overlays ab.
Nutze lieber inset: 0, statt top, right, bottom und left einzeln zu schreiben.
Ein fixed-Element in irgendetwas mit transform, filter, perspective oder contain: paint ist nicht mehr am Bildschirm fixiert. Verschiebe es ans Ende von body oder rendere es in einem Portal.
Positionierte Elemente werden standardmäßig über statischen gezeichnet. Greife nur zu z-index, wenn sich zwei positionierte Elemente überlappen.
Häufige Fragen
Was ist der Unterschied zwischen absolute und relative?
relative verschiebt ein Element optisch, lässt aber seinen ursprünglichen Platz im Layout bestehen, sodass sich nichts drumherum bewegt. absolute nimmt das Element komplett aus dem Layout, Nachbarn schließen die Lücke, und top oder left werden vom nächsten positionierten Vorfahren aus gemessen statt von der Stelle, an der es gewesen wäre.
Warum funktioniert position: sticky nicht?
Die üblichen Ursachen sind ein fehlender top-Wert, ein Vorfahre mit overflow hidden oder auto oder ein Elternelement, das nicht höher ist als das sticky-Element. Arbeite die Checkliste auf dieser Seite der Reihe nach ab; die ersten beiden Punkte erfassen die meisten Fälle.
Woran orientiert sich absolute?
An seinem Containing Block: der Padding-Box des nächsten Vorfahren, dessen position etwas anderes als static ist. Vorfahren mit transform, filter oder bestimmten contain-Werten zählen ebenfalls. Gibt es keinen, ist es der initiale Containing Block, der die Größe des Viewports hat.
Warum bewegt sich mein fixierter Header mit der Seite?
Ein Vorfahre hat transform, perspective, filter, backdrop-filter, will-change: transform oder contain: paint. Jede dieser Eigenschaften macht diesen Vorfahren zum Containing Block für fixed-Nachkommen, sodass der Header an ihm fixiert ist statt am Bildschirm.
Was ist inset in CSS?
Eine Kurzschreibweise für top, right, bottom und left, die demselben Muster mit einem bis vier Werten folgt wie margin. inset: 0 spannt ein positioniertes Element über seinen ganzen Containing Block. inset-inline und inset-block setzen die Paare für jede Achse.
Der Containing Block, einfach erklärt
Jeder Offset braucht ein Bezugsrechteck. Für static- und relative-Elemente ist es die Content-Box des Elternelements. Für absolute ist es die Padding-Box des nächsten positionierten Vorfahren, Padding auf der Karte schiebt ein absolute-Kindelement also nicht nach innen.
Für fixed ist es normalerweise der Viewport. Das ändert sich, wenn ein Vorfahre transform, perspective, filter, backdrop-filter, contain: paint oder einen passenden will-change-Wert bekommt: Dann wird der Vorfahre zum Bezug und das Element scrollt mit ihm. Die Demo auf dieser Seite nutzt genau das, damit ihre fixed-Box im Demo-Rahmen bleibt.
Zentrieren mit absoluter Positionierung
Bei bekannter Größe setzt inset: 0 plus margin: auto die Box exakt in die Mitte und hält die Pixelkanten scharf. Bei unbekannter Größe funktionieren top: 50% und left: 50% gefolgt von translate(-50%, -50%) für jeden Inhalt.
Beide nehmen die Box aus dem Fluss, das Elternelement wächst also nicht um sie herum. Wenn sich das Elternelement nach dem Inhalt richten soll, zentriere stattdessen mit Grid oder Flex.
Jeder Wert im Detail
position-Werte
Wert
Fluss
Was Offsets bewirken
Typische Verwendung
Bleibt im Fluss
Werden ignoriert
Der Standard. Hier fängt alles an.
Bleibt im Fluss, sein ursprünglicher Platz bleibt erhalten
Verschieben es von der Stelle, an der es wäre
Kleine Verschiebungen und als Anker für absolute Kindelemente.
Was einen Containing Block für absolute und fixed erzeugt
Vorfahren, die positionierte Nachkommen einfangen (laut MDN)
Vorfahre hat
Nutzen absolute-Kinder ihn?
Nutzen fixed-Kinder ihn?
position: relative, absolute, fixed oder sticky
Ja
Nein
transform, perspective, rotate, scale oder translate mit einem anderen Wert als none
Ja
Ja
filter oder backdrop-filter mit einem anderen Wert als none
Ja
Ja
contain: layout, paint, strict oder content
Ja
Ja
will-change mit einer dieser Eigenschaften, etwa transform oder filter
Ja
Ja
content-visibility: auto
Ja
Ja
Muster, die du brauchen wirst
Badge an der Ecke einer Karte
Die Karte ist der positionierte Vorfahre. Negative Offsets schieben das Badge zur Hälfte über die Ecke hinaus.
Sticky Tabellenkopf
Der Wrapper scrollt, daher klebt th mit top: 0 an ihm. Der Hintergrund verhindert, dass Zeilen durchscheinen.
Kurzschreibweise inset
Dasselbe Muster wie bei margin: ein Wert für alle Seiten, zwei für vertikal und horizontal, vier im Uhrzeigersinn ab oben.
Du hast einen Schwellenwert gesetzt: top, bottom, left oder right. Ohne ihn verhält sich sticky wie relative.
Kein Vorfahre zwischen dem Element und dem Scroller hat overflow: hidden, auto oder scroll. Jeder davon wird zum Scroller, oft zu einem, der nie scrollt. overflow: clip erzeugt keinen Scroll-Container.
Das Elternelement ist höher als das sticky-Element. Es klebt nur, solange sein Elternelement auf dem Bildschirm ist, und verschwindet dann mit ihm.
In einer Flex- oder Grid-Zeile ist das Element nicht auf volle Höhe gestreckt. Ergänze align-self: start, damit es Platz zum Bewegen hat.
Das sticky-Element liegt über dem Inhalt, der darunter scrollt. Gib ihm einen Hintergrund und einen z-index, wenn Inhalt durchscheint.
Gescrollt wird tatsächlich in dem Vorfahren, den du vermutest. Prüfe in den DevTools, welches Element die Scrollleiste hat.
Position-Playground
position-Wert
Elternelement hat position: relative
Offsets werden ignoriert. Die Box sitzt im normalen Fluss zwischen den Absätzen.
Die Box wird verschoben gezeichnet, aber die Lücke, wo sie wäre, bleibt erhalten. Nachbarn bewegen sich nicht.
Gemessen vom gestrichelten Elternelement, das position: relative hat.
Kein positioniertes Elternelement, daher wird vom scrollenden Demo-Bereich aus gemessen, dem nächsten positionierten Vorfahren darüber.
Beim Scrollen am Demo-Rahmen fixiert. Der Rahmen hat ein transform, das ihn statt des Browserfensters zum Containing Block macht.
Scrollt mit dem Text, bis es top Pixel vom oberen Rand des Scrollers entfernt ist, und hält dann, bis sein Elternelement wegscrollt.
Scrollbarer Demo-Bereich
Scrolle in diesem Rahmen. Der Text ist Fülltext, damit es etwas zum Vorbeiscrollen gibt.
Elternelement
Erster Absatz vor der Box.
Absatz nach der Box. Achte darauf, ob er nach oben rückt, wenn die Box den Fluss verlässt.
Zeile {n} mit zusätzlichem Inhalt zum Scrollen.
Inhalt nach dem Elternelement, Zeile {n}.
CSS kopieren
Warum fixed im Rahmen bleibt: Der Rahmen hat transform: translateZ(0). Jedes transform macht ein Element zum Containing Block für fixed-Nachkommen. Auf einer echten Seite ohne einen solchen Vorfahren hängt fixed am Browserfenster.
Sticky funktioniert nicht: Checkliste
Sticky Header hinter anderem Inhalt versteckt? Siehe