CSS Anchor Positioning

Ein Element an einem beliebigen anderen Element ausrichten – egal, wo im DOM es steht. Kein position: relative-Wrapper mehr nötig, keine Höhen-/Breiten-Berechnungen in JavaScript.


POSITIONIERUNG & DOM

Klassisches position: absolute löst nur Eltern-Kind-Beziehungen im DOM – ein Tooltip muss deshalb zwingend im selben, position: relative-positionierten Wrapper wie sein Trigger stecken. Liegen Trigger und Tooltip im Markup weit auseinander (z. B. weil ein Elternelement overflow: hidden hat), bricht das Prinzip zusammen.

CSS Anchor Positioning löst dieses Limit auf: ein Element kann sich an einem beliebigen anderen Element im DOM orientieren, unabhängig von dessen Position im Markup.


Grundsyntax

Zwei Eigenschaften plus eine Funktion reichen aus:

  • anchor-nameVergibt dem Anker-Element einen frei wählbaren Namen (wie eine CSS-Variable)
  • position-anchorVerweist beim positionierten Element auf diesen Namen
  • anchor()Liest Kanten oder Mittelpunkt des Ankers aus, z. B. für top/left
.anchor {
    anchor-name: --my-anchor;
}

.tooltip {
    position: absolute;
    position-anchor: --my-anchor;
    top: anchor(bottom);   /* direkt unter dem Anker */
    left: anchor(center);  /* horizontal zentriert */
}

Ein Element kann mehrere Namen erhalten:

.anchor {
    anchor-name: --tooltip --menu;
}

Beispiel

Anker-Element und Hinweisbox liegen hier absichtlich nicht ineinander verschachtelt im Markup – trotzdem findet die Hinweisbox ihren Anker.

Ich bin der Anker
Ich richte mich am Anker aus
<span class="anchor">Ich bin der Anker</span>
<div class="tooltip">...</div>

<style>
.anchor {
    anchor-name: --demo-anchor;
}

.tooltip {
    position: absolute;
    position-anchor: --demo-anchor;
    top: anchor(bottom);
    left: anchor(center);
    translate: -50% 10px;
}
</style>

position-anchor – Anker zuweisen

  • normalVerwendet einen impliziten Anker, wenn position-area gesetzt ist
  • noneKein Standard-Anker
  • autoVerwendet einen impliziten Anker, falls einer vorhanden ist
  • --nameVerwendet das Element mit diesem anchor-name
  • match-parentÜbernimmt den Standard-Anker des Elternelements

Ein impliziter Anker kann durch eine andere API entstehen. Bei einem Popover ist beispielsweise der Button mit popovertarget der implizite Anker.


Mehrere Anker mit nth-child

Bei mehreren Anker-Elementen erhält in diesem Beispiel jedes Anker-Tooltip-Paar einen eigenen anchor-name. So lässt sich jedes Tooltip eindeutig dem gewünschten Anker zuordnen. :nth-child() adressiert dabei jedes Paar einzeln. Die Tooltips sind hier zusätzlich standardmässig unsichtbar und werden bei Hover eingeblendet – geh mit der Maus über ein Icon. Auf Touchgeräten bleiben die Hinweise sichtbar.

A
B
C
Icon A
Icon B
Icon C
.icon:nth-child(1) { anchor-name: --icon-1; }
.icon:nth-child(2) { anchor-name: --icon-2; }
.icon:nth-child(3) { anchor-name: --icon-3; }

.icon-tip:nth-child(4) { position-anchor: --icon-1; }
.icon-tip:nth-child(5) { position-anchor: --icon-2; }
.icon-tip:nth-child(6) { position-anchor: --icon-3; }

Für den Hover-Effekt reicht CSS – Icon und Tooltip sind zwar nicht verschachtelt, aber Geschwister im DOM. Der allgemeine Geschwister-Kombinator ~ (im Gegensatz zum direkten +) matcht dabei jedes spätere Geschwister, nicht nur das unmittelbar folgende:

.icon:nth-child(1):hover ~ .icon-tip:nth-child(4) {
    opacity: 1;
}

anchor-scope – Namen begrenzen

anchor-name muss nicht auf der ganzen Seite eindeutig sein. Wird eine Komponente mehrfach verwendet, kann anchor-scope denselben Namen auf die jeweilige Komponente begrenzen. So verweist jede Hinweisbox auf den Anker innerhalb ihres eigenen Bereichs:

.card {
    anchor-scope: --card-anchor;
}

.card-title {
    anchor-name: --card-anchor;
}

.card-info {
    position: absolute;
    position-anchor: --card-anchor;
    position-area: block-end;
}
  • noneKeine Begrenzung, Standardwert
  • --nameBegrenzt den angegebenen Anchor-Namen auf den Bereich
  • allBegrenzt alle Anchor-Namen innerhalb des Bereichs

Ohne passenden Scope wird bei mehreren sichtbaren Elementen mit demselben Namen der nächste passende Vorfahr verwendet – oder sonst das letzte passende Element im DOM.


anchor() – Kanten & Mittelpunkt

anchor() kann für jede Positionierungs-Eigenschaft (top, right, bottom, left) auf unterschiedliche Kanten oder den Mittelpunkt des Ankers zugreifen.

  • anchor(top)Obere Kante des Ankers
  • anchor(bottom)Untere Kante des Ankers
  • anchor(left)Linke Kante des Ankers
  • anchor(right)Rechte Kante des Ankers
  • anchor(center)Mittelpunkt des Ankers (horizontal oder vertikal, je nach Eigenschaft)
  • anchor(start)Logische Startkante in der verwendeten Achse
  • anchor(end)Logische Endkante in der verwendeten Achse
  • anchor(inside)Gleiche Seite wie die verwendete Inset-Eigenschaft
  • anchor(outside)Gegenüberliegende Seite der Inset-Eigenschaft

Praxis-Tipp: anchor(center) liefert nur die Koordinate der Mitte – das positionierte Element selbst bleibt an seiner eigenen linken/oberen Kante ausgerichtet. Für echtes Zentrieren zusätzlich translate: -50% 0 (oder 0 -50%) ergänzen, wie im Beispiel oben.

Anchor direkt angeben

Wurde mit position-anchor ein Standard-Anker festgelegt, genügt anchor(bottom). Der Name kann aber auch direkt in der Funktion stehen. So lassen sich in einem Element verschiedene Anker verwenden:

.element {
    left: anchor(--first right);
    top: anchor(--second bottom, 0);
}

Der optionale letzte Wert ist ein Fallback. Kann der Anker nicht aufgelöst werden, verwendet top im Beispiel den Wert 0. Auch Prozentwerte sind möglich: anchor(0%) entspricht start, anchor(50%) entspricht center und anchor(100%) entspricht end.


position-area – Position vereinfachen

Für häufige Positionen rund um einen Anker ist position-area die einfachere Alternative zur anchor()-Funktion. Rund um den Anker entsteht dafür gedanklich ein 3×3-Raster. Die Hinweisbox wird hier unterhalb des Ankers positioniert und automatisch daran ausgerichtet:

  • block-startOberhalb des Ankers
  • block-endUnterhalb des Ankers
  • inline-startVor dem Anker, bei links nach rechts also links
  • inline-endNach dem Anker, bei links nach rechts also rechts
  • centerIm mittleren Bereich des Ankers
  • span-*Erweitert den Bereich über eine angrenzende Spur
.tooltip {
    position: absolute;
    position-anchor: --my-anchor;
    position-area: block-end;
    margin: 10px;
}

block-end bedeutet in einer horizontalen Schreibrichtung «unterhalb». Dadurch werden top, left und translate für diese Position nicht benötigt.

Zwei Werte legen die Position in beiden Achsen genauer fest. Physische Angaben wie top, right, bottom und left sind ebenfalls möglich:

position-area: block-end inline-start;
position-area: block-start span-inline-end;
position-area: bottom right;

Logische Werte passen sich der Schreibrichtung an und sind deshalb für flexible Layouts meist die bessere Wahl.

Mit anchor-center ausrichten

Die Werte für align-self und justify-self richten das positionierte Element innerhalb seines verfügbaren Bereichs aus. anchor-center zentriert es direkt über dem Standard-Anker:

.tooltip {
    position: absolute;
    position-anchor: --my-anchor;
    justify-self: anchor-center;
}

anchor-size() – Grösse übernehmen

Mit anchor-size() kann ein positioniertes Element die Breite oder Höhe seines Ankers übernehmen. Das ist beispielsweise für Dropdowns nützlich, die mindestens so breit wie der auslösende Button sein sollen:

ANKER: 240 PX GLEICHE BREITE MIT anchor-size(width)
.dropdown {
    position: absolute;
    position-anchor: --menu-button;
    position-area: block-end;
    min-width: anchor-size(width);
}
  • widthBreite des Ankers
  • heightHöhe des Ankers
  • inlineGrösse in der Inline-Achse des umgebenden Blocks
  • blockGrösse in der Block-Achse des umgebenden Blocks
  • self-inlineInline-Achse des positionierten Elements
  • self-blockBlock-Achse des positionierten Elements

Der Anchor-Name und ein Fallbackwert können direkt in der Funktion stehen:

width: anchor-size(--menu-button width, 12rem);

Ohne Grössenangabe wird die Achse aus der verwendeten Eigenschaft abgeleitet: width: anchor-size() entspricht width: anchor-size(width).


position-try-fallbacks – automatisches Umklappen

Was passiert, wenn ein anker-positioniertes Element sonst über den Viewport-Rand hinausragen würde? position-try-fallbacks lässt den Browser automatisch eine Alternativ-Position ausprobieren, sobald die erste nicht mehr passt – ohne manuelles max-width- oder Umbruch-Gefrickel.

ANKER Kein Platz unten – ich klappe nach oben.
.tooltip {
    position: absolute;
    position-anchor: --my-anchor;
    top: anchor(bottom);
    left: anchor(center);
    position-try-fallbacks: flip-block, flip-inline;
}
  • flip-blockKlappt auf die andere Seite der Block-Achse (z. B. topbottom)
  • flip-inlineKlappt auf die andere Seite der Inline-Achse (z. B. leftright)
  • flip-xSpiegelt entlang der horizontalen Achse
  • flip-ySpiegelt entlang der vertikalen Achse
  • flip-startSpiegelt Start- und Endrichtungen diagonal

Praxis-Tipp: Der Browser übernimmt die Berechnung, welche Seite gerade genug Platz hat – eleganter als das Overflow-Problem selbst mit fixen Grössenangaben abzufangen.

position-try-order

Standardmässig prüft der Browser die Fallbacks in der angegebenen Reihenfolge. position-try-order kann stattdessen die Variante mit dem meisten verfügbaren Platz bevorzugen:

  • normalReihenfolge aus position-try-fallbacks
  • most-widthVariante mit der grössten Breite zuerst
  • most-heightVariante mit der grössten Höhe zuerst
  • most-inline-sizeGrösster Platz in der Inline-Achse
  • most-block-sizeGrösster Platz in der Block-Achse
.tooltip {
    position-try-fallbacks: flip-block, flip-inline;
    position-try-order: most-height;
}

Eigene Fallbacks mit @position-try

Reichen die eingebauten Flip-Varianten nicht aus, definiert @position-try eine eigene Alternativposition. Der frei gewählte Name wird anschliessend in position-try-fallbacks verwendet:

@position-try --above {
    position-area: block-start;
    max-height: 40vh;
}

.tooltip {
    position-area: block-end;
    position-try-fallbacks: --above, flip-inline;
}

Innerhalb von @position-try sind Eigenschaften für Position, Abstände, Grösse, Ausrichtung, position-anchor und position-area erlaubt.


position-visibility – bei Bedarf ausblenden

position-visibility blendet ein anker-positioniertes Element abhängig von seinem Anker oder dem verfügbaren Platz aus:

  • alwaysImmer anzeigen
  • anchor-validAusblenden, wenn der Anker nicht aufgelöst werden kann
  • anchor-visibleAusblenden, wenn der Anker nicht sichtbar oder vollständig abgeschnitten ist
  • no-overflowAusblenden, wenn das Element trotz Fallback überläuft
.tooltip {
    position-visibility: anchor-visible no-overflow;
}

Mehrere Bedingungen lassen sich kombinieren. anchor-visible ist der Standardwert.


Semantik & Barrierefreiheit

Anchor Positioning erzeugt nur eine visuelle Beziehung. Es macht aus einem Element weder automatisch einen Button noch verknüpft es Tooltip und Anker für assistive Technologien. Die semantische Beziehung muss deshalb weiterhin mit passenden HTML-Elementen und – falls nötig – ARIA-Attributen hergestellt werden.


Browser-Support

Die Grundfunktionen anchor-name, position-anchor und anchor() sind seit 2026 Baseline. Die weiterführenden Eigenschaften entwickeln sich noch und können je nach Browser unterschiedlich weit unterstützt sein. Deshalb einzelne Funktionen mit @supports prüfen und für ältere Browser auf die klassische relative/absolute-Lösung zurückfallen:

@supports not (anchor-name: --x) {
  .tooltip {
    /* Fallback: klassische relative/absolute Lösung */
    position: static;
  }
}

Wann lohnt sich anchor()?

Noch kein genereller Ersatz für position: relative/absolute im Alltag – für die meisten Fälle (Badges, einfache Dropdowns innerhalb eines Containers) reicht die klassische Lösung völlig. Anchor Positioning lohnt sich vor allem, wenn Trigger und positioniertes Element im DOM weit auseinanderliegen müssen:

  • Custom Dropdowns/Select-Menüs, die aus einem overflow: hidden-Container ausbrechen müssen
  • Kontextmenüs, die sich an der Klickposition orientieren, aber unabhängig vom auslösenden Element im DOM liegen
  • Popover/Tooltip-Bibliotheken, die ihr Markup ans Ende von <body> "teleportieren" (klassisches Z-Index-Problem), sich aber trotzdem visuell am Trigger orientieren sollen
  • Formular-Validierungs-Tooltips, die neben dem jeweiligen Input erscheinen sollen, aber zentral verwaltet werden

Die native popover-API kombiniert Popover-Verhalten oft direkt mit Anchor Positioning – dazu mehr in der eigenen Popover-Lektion.


Kurz gesagt

  • anchor-name auf dem Anker-Element vergeben
  • position-anchor beim positionierten Element darauf verweisen lassen
  • anchor-scope begrenzt wiederverwendete Namen auf eine Komponente
  • anchor() liest Kanten/Mittelpunkt des Ankers aus – kombinierbar mit translate zum Zentrieren
  • position-area positioniert ein Element in einem Bereich rund um den Anker
  • anchor-size() übernimmt Breite oder Höhe des Ankers
  • position-try-fallbacks und @position-try definieren Alternativen bei zu wenig Platz
  • position-visibility blendet unpassend positionierte Elemente bei Bedarf aus
  • Bei mehreren Ankern können eigene Namen die Zuordnung vereinfachen, z. B. über :nth-child()
  • Kein position: relative-Wrapper mehr nötig – Trigger und positioniertes Element können beliebig weit auseinander im DOM liegen
  • Baseline seit 2026, aber: für die meisten Alltagsfälle reicht klassisches relative/absolute weiterhin

Nurse Siehe auch CSS Position.