Ankerpositionierung

Wenn Sie ein Kurzinfo- oder Drop-down-Menü platzieren, möchten Sie es oft relativ zu einem anderen Element auf der Seite positionieren. Bisher war es möglich, diesen Effekt mit absoluter Positionierung zu erzielen. Bei komplexeren Anforderungen mussten Elemente jedoch mit JavaScript positioniert werden.

Mit der CSS-Ankerpositionierung lässt sich ein Element deklarativ relativ zu einem anderen Element positionieren.

Elemente verbinden

Damit ein Element zu einem Anker wird, geben Sie ihm einen anchor-name-Wert, der mit zwei Bindestrichen beginnt. Dies ist die Kennung, mit der das positionierte Element seinen Anker findet. Es ist hilfreich, ihr einen beschreibenden Namen zu geben. Sie können einem Element sogar mehrere Ankernamen geben, wenn es auf unterschiedliche Weise als Anker verwendet wird.

Sie müssen einige Eigenschaften für das positionierte Element festlegen, damit es verankert werden kann. Zuerst müssen Sie das Element aus dem Fluss des Dokuments herausnehmen, damit es schwebt. Dazu legen Sie position: absolute oder position: fixed fest.

Als Nächstes müssen Sie festlegen, an welchem Anker Sie die Verbindung herstellen möchten. Dazu setzen Sie position-anchor auf den Namen des Ankers, den Sie für den Anker festgelegt haben.

Schließlich müssen Sie festlegen, wie der Anker positioniert werden soll. Weitere Informationen zu position-area finden Sie später in diesem Modul.

#anchor {
   anchor-name: --my-anchor;
}

#positionedElement {
     position: absolute;
     position-anchor: --my-anchor;
     position-area: end;
}

Implizite Verbindungen

Pop-overs lassen sich noch einfacher anbinden. Wenn Sie ein Popover über eine Schaltfläche mit einem popovertarget öffnen oder ein source mit showPopover({source}) festlegen, ist für das Popover bereits ein „impliziter Anker“ festgelegt. Da ein Pop-over standardmäßig mit position: fixed schwebt, müssen Sie nur die Position festlegen, um es zu positionieren.

#anchor{}

#positionedElement {
  position-area: end;
  margin: unset;
}

Mögliche Anker eingrenzen

Sie können die Ankerpositionierung als Teil einer Komponente implementieren, sodass Sie ein Muster wie ein Drop-down-Menü an mehreren Stellen verwenden können. Wenn Sie dasselbe anchor-name mehrmals verwenden, wie stellen Sie sicher, dass jedes positionierte Element den richtigen Anker findet?

Bei JavaScript-Lösungen müssen Sie jedem Anker eindeutige IDs hinzufügen und dann vom positionierten Element darauf verweisen. Das ist umständlich. CSS bietet mit anchor-scope eine einfachere Lösung.

Mit der Property anchor-scope wird festgelegt, welche Ankernamen nur für ein Element und seine Nachfolger abgeglichen werden. Es akzeptiert eine Liste mit einem oder mehreren Ankernamen oder das Schlüsselwort all, um den Bereich aller definierten Ankernamen einzuschränken.

Ein anchor-scope wird idealerweise einem übergeordneten Element sowohl des positionierten Elements als auch des Ankerelements hinzugefügt, das keine anderen Ankerelemente mit demselben Namen enthält. Häufig befindet sich das Attribut im Stamm der wiederverwendbaren Komponente.

Das folgende Beispiel zeigt den Unterschied, den anchor-scope macht, wenn es auf wiederholte Elemente mit demselben anchor-name angewendet wird. Im Beispiel verweisen alle <img>-Elemente und die Bildbanner auf den Ankernamen --image. Wenn anchor-scope auf die <li>-Elemente angewendet wird, entspricht position-anchor: --image nur dem <img>-Element innerhalb desselben <li>-Elements wie das Banner. Andernfalls entspricht es dem zuletzt gerenderten <img>.

Positionierung

Nachdem Sie das Element an den Anker gebunden haben, können Sie es positionieren. Für die Ankerpositionierung gibt es zwei Methoden: position-area und die Funktion anchor().

position-area

Mit der Eigenschaft position-area können Sie ein Element um den Anker herum positionieren, indem Sie ein oder zwei Keywords angeben. Damit werden viele gängige Anwendungsfälle abgedeckt und es ist oft ein guter Ausgangspunkt.

So funktioniert position-area

position-area funktioniert, indem ein neuer enthaltender Block für das positionierte Element in einem Bereich erstellt wird, der durch die Kanten des Ankers und des ursprünglichen enthaltenden Blocks des positionierten Elements generiert wird.

Es gibt viele Keywords für position-area, aber sie lassen sich in einige Kategorien unterteilen, um sie verständlicher zu machen. Anchor-tool.com ist ein großartiges Tool, um die Syntax zu erkunden.

Physische Schlüsselwörter

Sie können die physischen Keywords top, left, bottom, right und center verwenden. Mit position-area: top right wird das positionierte Element beispielsweise über und rechts vom Anker platziert. Für diese Keywords gibt es auch Entsprechungen für die physischen Achsen: y-start, x-start, y-end und x-end.

Logische Keywords

Sie können auch die logischen Keywords block-start, block-end, inline-start und inline-end verwenden. Mit position-area: block-end inline-start wird das positionierte Element beispielsweise in Sprachen wie Deutsch unter und links vom Anker platziert. Im Schreibmodus des Dokuments wird es nach dem Anker auf der Blockachse und vor dem Anker auf der Inlineachse platziert. center kann auch mit einem logischen Schlüsselwort verwendet werden.

Sie können die Achse auch weglassen, wenn Sie logische Keywords angeben, wobei die Blockachse zuerst und die Inline-Achse an zweiter Stelle steht. position-area: start end ist mit position-area: block-start inline-end oder sogar position-area: inline-end block-start identisch.

Über mehrere Rasterbereiche

Bisher haben Sie vielleicht bemerkt, dass Sie mit diesen Optionen das positionierte Element nur in einem einzelnen Rasterbereich platzieren können. Wenn Sie physischen oder logischen Properties das Präfix span hinzufügen, wird der angrenzende Mittelpunkt des Rasters hinzugefügt. position-area: span-top right wird rechts vom Anker und vom unteren Rand des Ankers bis zum oberen Rand des ursprünglichen enthaltenden Blocks des positionierten Elements platziert.

Eine gängige Position für ein Drop-down-Menü ist position-area: block-end span-inline-end.

Das Schlüsselwort span-all erstreckt sich über 3 Zeilen oder Spalten.

Einzelnes Keyword

Wenn Sie nur ein Keyword festlegen, wird die andere Achse automatisch festgelegt. Das funktioniert weitgehend wie erwartet, aber es kann hilfreich sein, die Funktionsweise zu verstehen.

Wenn die Achse des angegebenen Keywords eindeutig ist, wird die andere Achse als span-all berechnet. Das bedeutet, dass position-area: bottom position-area: bottom span-all entspricht und das positionierte Element unter dem Anker platziert wird und die gesamte Breite des enthaltenden Blocks zur Verfügung hat.

Wenn das Keyword dagegen keine Achse angibt, wird es wiederholt. position-area: start entspricht start start und wird in rechtsläufigen Sprachen links oben am Anker platziert.

Die anchor()-Funktion

Für komplexere Anwendungsfälle erfüllt position-area möglicherweise nicht Ihre Anforderungen. Mit der Funktion anchor() können Sie einzelne Inset-Eigenschaften basierend auf der Position eines anderen Elements festlegen. Dies wird in eine CSS-Länge aufgelöst, sodass Sie sie in Berechnungen und mit anderen CSS-Funktionen verwenden können. Außerdem können Sie verschiedene Seiten an unterschiedliche Anker binden.

Für die Funktion anchor() sind ein Ankername und eine Ankerseite erforderlich. Wenn Ihr Element einen Standardanker hat, der entweder mit position-anchor oder implizit (z. B. mit einem Pop-over) festgelegt wurde, können Sie den Ankernamen weglassen.

.positionedElement {
  block-start: anchor(--my-anchor start);
  /*  OR  */
  position-anchor: --my-anchor;
  block-start: anchor(start);
}

Fallback-Werte

Wenn kein Anker für eine anchor()-Funktion gefunden werden kann, ist die gesamte Deklaration ungültig. Das kann passieren, wenn der Anker nach dem positionierten Element gerendert wird oder kein Element mit übereinstimmendem anchor-name vorhanden ist. Um dies zu beheben, können Sie eine Fallback-Länge oder einen Fallback-Prozentsatz festlegen.

.positionedElement {
   block-start: anchor(--my-anchor, 100px)
}

Im vorherigen Beispiel ist der linke Wert des positionierten Elements an --focused-anchor verankert, aber anchor-name ist nur vorhanden, wenn der Mauszeiger auf den ersten Button bewegt wird oder dieser den Fokus erhält. Da eine anchor()-Funktion in eine Länge aufgelöst wird, können Sie einen anderen Anker als Fallback verwenden. Ohne Fallback würde das positionierte Element nicht positioniert.

Ankerseiten-Keywords

Mit dem Wert für die Ankerseite wird festgelegt, an welcher Kante des Ankers die Positionierung erfolgen soll. Ähnlich wie bei position-area werden für den Wert der Ankerseite verschiedene Arten von Syntax unterstützt.

Typ Werte Beschreibung
Physisch top, left, bottom, right

Physische Keywords entsprechen einer bestimmten Seite des Ankers, können aber nur auf derselben Achse wie der Inset des positionierten Elements verwendet werden, das Sie festlegen.

Mit top: anchor(bottom) wird beispielsweise die Oberkante des Elements an der Unterkante des Ankers positioniert. left: anchor(top) funktioniert jedoch nicht.

Seite inside, outside

Das Keyword inside entspricht derselben Seite wie die Inset-Eigenschaft und das Keyword outside der gegenüberliegenden Seite auf derselben Achse.

inset-block-start: anchor(inside) bezieht sich beispielsweise auf die block-start-Seite des Ankers und inset-inline-end: (outside) auf die inline-start-Seite.

Logisch start, end, self-start, self-end

Logische Keywords beziehen sich auf die Seiten des Ankers basierend auf dem Schreibmodus des positionierten Elements mit self-start und self-end oder auf dem Schreibmodus des enthaltenden Blocks des positionierten Elements mit start und end.

Prozentsatz 0 % bis 100%

Mit einem Prozentwert wird das positionierte Element entlang der Achse vom Start bis zum Ende des Ankers auf der angegebenen Achse platziert. 0% befindet sich auf der start-Seite des Ankers und 100% auf der Endseite des Ankers. center entspricht 50%. Wenn Sie einen Prozentsatz für einen Inset auf der Endseite wie bottom verwenden, wird dieser nicht umgekehrt. 0% ist weiterhin die start-Seite des Ankers.

In diesem Beispiel sehen Sie, wie ein Prozentwert immer vom Anfang bis zum Ende auf der angegebenen Achse verläuft:

anchor() verwenden

Da anchor() eine Länge ist, ist sie sehr flexibel. Sie können den Wert mit CSS-Funktionen wie max() und calc() bearbeiten.

Eine Einschränkung besteht darin, dass Sie anchor()-Funktionen nur für Inset-Eigenschaften verwenden können.

Im vorherigen Beispiel wird ein Hintergrund hinter dem geöffneten Detailbereich hinzugefügt, der sich beim Öffnen eines anderen Bereichs sanft animiert und sich streckt, um einen Detailbereich einzuschließen, auf den der Mauszeiger bewegt wird. Dazu wird min() verwendet, um die kürzere Länge zwischen zwei Ankern auszuwählen.

#indicator{
/*  Use the smaller of the 2 values:  */
  inset-block-start: min(
/*   1. The start side of the default anchor, which is the open `<details>` element  */
    anchor(start),
/*   2. The start side of the hovered `<details>` element.    */
    anchor(--hovered start,
/*     If no `<details>` element is hovered, this falls back to infinity px, so that the other value is smaller, and therefore used.   */
       var(calc(1px * infinity)))
  );
}

Im Beispiel wird auch calc() verwendet, um Inline-Abstand um den geöffneten Bereich hinzuzufügen.

Größe des Ankers verwenden

Mit der Funktion anchor-size() können Sie auch die Abmessungen des Ankers für die Größe, Position oder den Rand des positionierten Elements verwenden.

anchor-size() verwendet einen Ankernamen oder den Standardanker. Standardmäßig wird die Größe des Ankers auf der Achse verwendet, auf der er eingesetzt wird. width: anchor-size() gibt also die Breite des Ankers zurück. Sie können auch die andere Achse verwenden, indem Sie mit den physischen Keywords width und height oder den logischen Keywords block, inline, self-block und self-inline die gewünschte Länge angeben.

Überlauf behandeln

Sie haben eine Drop-down-Menükomponente erstellt und das Drop-down-Menü mithilfe der Ankerpositionierung an der gewünschten Stelle platziert. Dann verschieben Sie das Menü auf die andere Seite des Bildschirms oder verwenden es für ein Nutzermenü und der Name des Nutzers ist sehr lang. Plötzlich ist das Drop-down-Menü nicht mehr auf dem Bildschirm zu sehen. Was heißt das für die Zukunft?

Die CSS-Ankerpositionierung bietet ein integriertes System, mit dem Sie schnell eine robuste Reihe von Fallbacks erstellen können, wenn sich das positionierte Element außerhalb des enthaltenden Blocks befindet.

Fallback-Optionen

Die position-try-fallbacks-Regel akzeptiert eine Liste von Fallback-Optionen. Wenn die Standardposition überläuft, wird jede Option in der Reihenfolge ausprobiert, bis eine Position gefunden wird, die nicht überläuft.

Sie können einen beliebigen position-area-Wert als Fallback-Option verwenden. In diesem Beispiel wird das positionierte Element in Schreibmodi von links nach rechts wie Englisch unten am Anker positioniert und erstreckt sich über die mittleren und rechten Spalten. Wenn das nicht möglich ist, wird versucht, es unten am Anker zu positionieren und dabei die linke und die mittlere Spalte zu überspannen. Wenn auch das überläuft, wird die Position auf die Standardposition zurückgesetzt, auch wenn diese überläuft.

.positioned-element {
  position-area: block-end span-inline-end;
  position-try-fallbacks: block-end span-inline-start;
}

Es gibt auch mehrere flip--Schlüsselwörter, mit denen häufige Fallback-Szenarien abgedeckt werden. Mit flip-block und flip-inline wird versucht, das Element über die Block- und Inline-Achsen zu spiegeln. Sie können auch mit flip-block flip-inline kombiniert werden, um beide Achsen zu tauschen. Der Wert flip-start spiegelt das positionierte Element über eine diagonale Linie von den Start- bis zu den Endpunkten des Ankers.

Sie können auch eine benutzerdefinierte Fallback-Option mit @position-try erstellen. So können Sie die Ränder und die Ausrichtung festlegen und sogar den Anker ändern.

@position-try --menu-below {
  position-area: bottom span-right;
  margin-top: 1em;
}

#positioned-element {
  position-try: --menu-below;
}

flip-block und flip-inline können den @position-try-Fallback-Optionen hinzugefügt werden, um eine Variante zu erstellen.

#positioned-element {
  position-try: --menu-below, flip-inline --menu-below;
}

Im vorherigen Beispiel führt der Browser die folgenden Schritte aus und stoppt, sobald er eine Lösung findet, die nicht überläuft.

  1. Das Element wird mit position-area: end unten rechts vom Anker platziert.
  2. Wenn das Element überläuft, wird es mit der benutzerdefinierten Fallback-Option --bottom-span-right platziert, die es mit position-area: bottom span-right und einem zusätzlichen unteren Rand platziert.
  3. Wenn das Element überläuft, wird es mit flip-inline --bottom-span-right platziert. Dabei wird die benutzerdefinierte Fallback-Option mit flip-inline kombiniert, was im Grunde position-area: bottom span-left entspricht.
  4. Wenn das Element überläuft, wird es mit der benutzerdefinierten Fallback-Option --use-alternate platziert, wodurch es unter einem ganz anderen Anker platziert wird.
  5. Wenn das Element überläuft, wird es mit position-area: end an seiner ursprünglichen Position platziert, obwohl bekannt ist, dass es überläuft.

Fallback-Reihenfolge

Wenn die ursprüngliche Position überläuft, versucht der Browser standardmäßig jede Option in position-try-fallbacks, bis eine Position gefunden wird, die nicht überläuft. Sie können dieses Verhalten mit position-try-order überschreiben, um jede Fallback-Option zu testen und diejenige zu verwenden, die auf einer bestimmten Achse den meisten Platz bietet.

Sie können die Achse entweder mit den logischen Keywords most-block-size und most-inline-size oder mit den physischen Keywords most-height und most-width angeben.

position-try-order und position-try-fallbacks können mit der Kurzform position-try kombiniert werden, wobei die Reihenfolge zuerst angegeben wird.

Scrollen

Wenn ein Nutzer scrollt, erwartet er, dass sich die Seite flüssig bewegt. Aus diesem Grund gibt es in Browsern Einschränkungen für die Verwendung der Ankerpositionierung beim Scrollen.

Sie können ein positioniertes Element zwar an Anker in verschiedenen Scrollcontainern binden, das Element bewegt sich jedoch nur, wenn einer der Anker gescrollt wird. Dies ist der Standardanker, der entweder der implizite Anker aus einem Pop-over oder der Wert von position-anchor ist.

Das positionierte Element bleibt sichtbar, auch wenn der Anker aus dem Blickfeld gescrollt wird. Wenn das positionierte Element ausgeblendet werden soll, wenn der Anker ausgeblendet ist, legen Sie position-visibility: anchors-visible fest. Das gilt nicht nur, wenn der Anker über das Ende des sichtbaren Bereichs hinaus gescrollt wird, sondern auch, wenn er auf andere Weise ausgeblendet wird, z. B. mit visibility: hidden.

Wissen testen

Welche Werte sind für die Seite in anchor() gültig?

inside
Richtig!
25%
Richtig!
25px
Falsch. Eine Länge wie 25px kann als Fallback-Wert verwendet werden, für die Seite sind jedoch nur Prozentangaben zulässig.
block-start
Falsch
start
Richtig!

Welche Werte sind für position-area gültig?

top
Richtig!
block-end inline-end
Richtig!
block-start block-end
Falsch. Sie können nur eine Spalte oder Zeile für jede Achse definieren.

Welche Attribute unterstützen die Funktion anchor()?

top
Richtig!
margin-left
Falsch.
inset-block-start
Richtig!
transform
Falsch.

Was passiert, wenn es mehrere Anker mit demselben anchor-name gibt?

Das positionierte Element wird dupliziert und an jede Übereinstimmung angehängt.
Falsch.
Das positionierte Element ist an das erste im Dokument gebunden.
Falsch.
Das positionierte Element ist an das letzte Element im Dokument gebunden.
Richtig!
Das positionierte Element ist am nächstgelegenen Anker befestigt.
Falsch.