position-try-fallbacks

Avatar of Juan Diego Rodríguez
Juan Diego Rodríguez am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Die CSS-position-try-fallbacks-Eigenschaft akzeptiert eine Liste von verschiedenen Optionen für ein "Ziel"-Element, um sich relativ zu einem "Anker"-Element durch Ausprobieren einer deklarierten Liste von kommagetrennten Optionen zu positionieren. Wenn die erste Option nicht genügend Platz hat, um das Ziel-Element anzuzeigen, versucht es die nächste Option und so weiter, ganz ähnlich wie Fallback-Schriften für font-family festzulegen.

.target {
  position: absolute;
  position-anchor: --my-anchor;
  inset-area: top left;
  position-try-fallbacks: flip-inline, inset-area(bottom left), --my-custom-position;
}

Zur Einordnung: Dies ist alles Teil der CSS Anchor Positioning-Spezifikation, einer Reihe von Funktionen, die zusammenarbeiten, um ein Element, das wir als "Ziel" bezeichnen können, relativ zu einem anderen, als "Anker" bezeichneten Element zu positionieren.

Hinweis: Die CSS-Spezifikationen bezeichnen die Eigenschaft als position-try-fallbacks, aber Chromium-Browser-Implementierungen bezeichnen sie zum Zeitpunkt der Erstellung dieses Artikels als position-try-options mit demselben Satz von Werten. Entweder kann sich die Spezifikation ändern oder Browser ihre Implementierungen in Zukunft zur Konsistenz aktualisieren. Bis dahin ist die Empfehlung, stattdessen die Kurzschrifteigenschaft position-try zu verwenden. Infolgedessen verwenden die Demos in diesem Artikel position-try-options.

Syntax

position-try-fallbacks: none | [ [<dashed-ident> || <try-tactic>] | inset-area( <'inset-area'> ) ]#
  • Initialwert: none
  • Gilt für: absolutely-positionierte Elemente
  • Vererbt: nein
  • Prozentwerte: n/v
  • Berechneter Wert: wie angegeben
  • Kanonische Reihenfolge: gemäß Grammatik
  • Animationstyp: diskret

Werte

/* Custom @try-position */
position-try-fallbacks: --my-custom-position;
position-try-fallbacks: --myCustomPosition;

/* <try-tactic> */
position-try-fallbacks: flip-block;
position-try-fallbacks: flip-inline;
position-try-fallbacks: flip-start;
position-try-fallbacks: flip-block flip-inline;

/* `<dashed-ident>` || `<try-tactic>` */
position-try-fallbacks: --my-custom-position flip-block;
position-try-fallbacks: --myCustomPosition flip-block flip-inline;

/* inset-area( <'inset-area'> ) */
position-try-fallbacks: inset-area(bottom center);
position-try-fallbacks: inset-area(top left);

/* All can be together! */
position-try-fallbacks: --my-custom-position, flip-block flip-inline, --my-custom-position flip-block, inset-area(top left);

Die Eigenschaft position-try-fallbacks akzeptiert eine Liste von kommagetrennten Optionen, um das Ziel-Element zu positionieren, wenn es seinen Container-Block überläuft. Die Reihenfolge ist, wie geschrieben, kann aber mit der Eigenschaft position-try-order gesteuert werden.

  • none: Lässt die Liste der Positionsoptionen des Ziels leer.
  • <dashed-ident>: Fügt der Optionsliste eine benutzerdefinierte @position-try-Option mit dem angegebenen Namen hinzu. Wenn keine übereinstimmende @position-try vorhanden ist, hat die Eigenschaft keine Auswirkung. Der Wert wird als "dashed" Ident bezeichnet, da er mit zwei Gedankenstrichen (--) vorangestellt werden muss.
  • <try-tactic>: Erstellt eine Optionsliste durch Umkehren der aktuellen Position des Ziels auf einer von drei Achsen, die jeweils durch ein eigenes Schlüsselwort definiert sind. Sie können auch kombiniert werden, um ihre Effekte zu addieren.

  • <dashed-ident> || <try-tactic>: Kombiniert eine benutzerdefinierte @try-option und eine <try-tactic>, um eine einzelne Optionsliste durch Umkehren der benutzerdefinierten @position-try, wie angegeben, zu erstellen. Die <try-tactic>-Schlüsselwörter können ebenfalls kombiniert werden, um ihre Effekte zu addieren.

  • inset-area( <'inset-area'> ): Die Verwendung der inset-area-Syntax um eine Wrapper-Funktion herum verschiebt das Ziel in eine neue inset-area.

Hinweis: Gemäß der Spezifikation existiert die Funktion inset-area( <'inset-area'> ) nicht, und die inset-area-Werte benötigen keinen Wrapper, aber Browser, die die Eigenschaft position-anchor implementiert haben, verwenden sie weiterhin.

Warum wir position-try-options brauchen

Das Positionieren von Elementen relativ zu einem Anker erscheint wie eine zweistufige Aufgabe: (1) Verknüpfen des Ziels mit einem Anker-Element und (2) Positionieren um diesen Anker herum. Ein Anker-Element kann sich jedoch *überall* auf der Seite befinden und seine Position aufgrund von Scrollen, Zoomen, Animationen usw. ändern. Infolgedessen kann ein Ziel-Element leicht Platzmangel haben, um sich relativ zum Anker zu positionieren, und seinen Container-Block (standardmäßig das Viewport) überlaufen.

Das ist ein normaler Vorgang; wir können nicht verhindern, dass ein Element beim Scrollen vom Bildschirm verschwindet, aber wir können die Erfahrung durch Maximierung seiner Bildschirmzeit verbessern.

Ein häufiger Anwendungsfall für Anker-Positionierung sind Tooltips, und diese haben das wiederkehrende Problem, dass sie etwas zu stark vom Bildschirm weg überlaufen. Beispielsweise überläuft ein Tooltip am oberen Rand eines Elements beim Scrollen nach unten.

Skeleton text with an overflowing tooltip at the top of an element

Traditionell wäre die einzige Möglichkeit, dies zu vermeiden, die Position des Tooltips dynamisch mit JavaScript zu ändern. Mit position-try-fallbacks können wir jedoch dasselbe nur mit CSS erreichen.

Skeleton text with a smart tooltip that doesn't overflow at the bottom of the element

Verwendung von position-try-options

Um die Eigenschaft position-try-fallbacks in CSS zu verwenden, benötigen wir unsere Hauptdarsteller: die Anker- und Ziel-Elemente.

<div class="anchor">My Anchor</div>
<div class="target">My Target</div>

und ein Hauch von CSS, um sie miteinander zu verbinden

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

.target {
  position: absolute;
  position-anchor: --my-anchor;
}

Wenn wir unser Ziel nicht auf spezielle Weise positionieren, wird es unter seinem Standardanker liegen. Wir können es mit der anchor()-Funktion entlang der Inset-Eigenschaften des Ziels oder mit der Eigenschaft inset-area nach oben verschieben. Welche Optionen Sie auch immer wählen, merken Sie sie sich für später.

.target {
  position: absolute;
  position-anchor: --my-anchor;

  inset-area: top;
  /* or */
  bottom: anchor(top);
}

Unser Ziel befindet sich über seinem Anker, aber das Problem tritt auf, wenn wir nach unten scrollen und das Ziel uns auf Wiedersehen winkend sehen, während es außerhalb des Viewports verschwindet. Dieses Ziel könnte ein Tooltip oder ein anderes Popover sein, das relevante Informationen zu seinem Anker-Element anzeigt, aber jetzt ist der Anker sichtbar und sein relevantes Ziel nicht.

Dies ist ein Problem, das uralt ist, und die besten Lösungen beinhalteten immer JavaScript, um ein Tooltip zu erreichen, das nicht vom Bildschirm verschwindet, oder sogar Bibliotheken wie Popper.js.

Mit position-try-fallbacks können wir eine Liste möglicher Positionen schreiben, wann immer unser Ziel außerhalb des Viewports gerät. Ihr Browser wird diese Optionen in der geschriebenen Reihenfolge versuchen, bis er eine findet, die nicht überläuft, oder die Optionen ausgehen.

inset-area( <'inset-area'> )

Um einfach anzufangen, haben wir die Wrapper-Funktion inset-area(), die alle Werte akzeptiert, die Ihre reguläre inset-area-Eigenschaft annehmen würde. Wir könnten eine Liste möglicher inset-area-Optionen angeben, und das Ziel wird sie ausprobieren, wenn es überläuft. Zum Beispiel, um das Ziel von oben nach unten zu bewegen.

.target {
  position: absolute;
  position-anchor: --my-anchor;

  inset-area: top;
  position-try-fallbacks: inset-area(bottom);
}

Wir könnten auch eine Liste mehrerer inset-area()-Funktionen angeben, um das Ziel bei Bedarf um seinen Anker herum zu bewegen

.target {
  position: absolute;
  position-anchor: --my-anchor;

  inset-area: top left;
  position-try-fallbacks:
    inset-area(top), inset-area(top right), 
    inset-area(right), inset-area(bottom), 
    inset-area(bottom right);
}

<dashed-ident>

Wir können benutzerdefinierte Positionsoptionen mithilfe der @position-try-Regel erstellen, um die Position des Ziels zu ändern. Sie akzeptiert fast jede Eigenschaft, die die Position des Elements ändern kann

  • Inset-Eigenschaften (top, left, bottom, right, inset-block, inset-inline, etc.)

  • Margin-Eigenschaften (margin, margin-block, margin-inline, etc.)

  • Größeneigenschaften (width, min-width, height, max-height, inline-size, block-size, etc.)

  • Selbstausrichtungseigenschaften (align-self, justify-self, place-self)

  • Position-Anker-Eigenschaften (position-anchor, inset-area)

Wir könnten also zum Beispiel unser Ziel kleiner machen, wenn es überläuft

@position-try --smaller-target {
  width: 50px;
}

.target {
  position: absolute;
  position-anchor: --my-anchor;
  inset-area: top;
  position-try-fallbacks: --smaller-target;

  width: 120px;
  aspect-ratio: 1;
}

Ich habe Ihnen gesagt, Sie sollen sich merken, ob Sie die anchor()-Funktion mit Inset-Eigenschaften *oder* die inset-area-Eigenschaft verwendet haben, um Ihren Anker zu positionieren. Warum? Weil deren Änderung mit der @try-position-Regel nicht funktioniert, wenn wir bei der ursprünglichen Deklaration inkonsistent sind. Zum Beispiel wird das folgende --custom-bottom nicht funktionieren, weil wir nicht die gleiche Methode zur Positionierung des Ziels verwenden.

@position-try --custom-bottom {
  width: 50px;
  top: anchor(bottom);
}

.target {
  /* ... */
  inset-area: top;
  position-try-fallbacks: --custom-bottom;
}

Wir müssen die Positionierungsmethoden anpassen

@position-try --custom-bottom {
  width: 50px;
  inset-area: bottom;
}

<try-tactic>

Der Wert <try-tactic> erstellt eine neue Positionsoption, indem er seine Position gemäß der angegebenen Versuchstaktik vertauscht. Er hat drei mögliche Schlüsselwörter, die jeweils angeben, welche Werte vertauscht werden, und das Ziel im Wesentlichen von einer Seite zur anderen ändern.

Das Schlüsselwort flip-block vertauscht die Werte auf der Block-Achse.

flip-block example. The anchor changes from the top to the bottom

Das Schlüsselwort flip-inline vertauscht die Werte auf der Inline-Achse.

flip-inline example. The anchor changes from the left to the right

Das Schlüsselwort flip-start vertauscht die Werte diagonal. Ich muss zugeben, dass flip-start eine seltsame <try-tactic> ist, die für mich immer noch etwas verwirrend ist. Bei Einzelwerten werden sie an einer angrenzenden Seite positioniert.

flip-start with a single value example. The target changes from the left to the top

Aber wenn das Ziel zwei Werte hat, werden sie in der gegenüberliegenden Ecke positioniert. Zumindest theoretisch, praktisch kann es das Ziel nur von der oberen rechten Ecke zur linken unteren und umgekehrt in LTR verschieben.

flip-start with two values example (LTR). The target changes from the right top side to the left bottom side

Und von der oberen linken Ecke zur unteren rechten und umgekehrt in RTL.

flip-start with two values example (RTL). The target changes from the left top side to the right bottom side

Wenn wir ein Ziel wollen, das sich in die gegenüberliegende Ecke dreht, unabhängig von der Textrichtung, können wir die Schlüsselwörter flip-block und flip-inline kombinieren. Es dreht zuerst den Anker auf der Block-Achse und dann auf der Inline-Achse.

flip-block and flip-inline example. The target goes from the left top to the left bottom, and ends up on the right bottom

Schließlich können wir den Wert flip-start mit flip-block oder flip-inline kombinieren, um das Ziel auf eine andere angrenzende Seite zu drehen.

flip-start and flip-block example. The target goes from the left side to the top, and ends up on the bottom

Die Reihenfolge ist wichtig, daher führt das Schreiben von flip-start flip-block zu einer anderen Position als flip-block flip-start. Bei letzterem wird zuerst das Schlüsselwort flip-block ausgeführt, und da sich das Ziel nicht auf der Block-Achse befindet, hat es keine Auswirkung und wird ignoriert.

flip-block and flip-start example. The target ignores the flip-block keyword and goes straight to the bottom

<dashed-ident> || <try-tactic>

Schließlich können wir sowohl eine benutzerdefinierte @try-position-Option als auch ein oder mehrere <try-tactic>-Schlüsselwörter kombinieren, wodurch eine neue Positionsoption entsteht und im Wesentlichen die @try-position-Eigenschaften vertauscht werden. Zum Beispiel die benutzerdefinierte Positionsoption…

@try-position --custom-right {
  inset-area: top;
  align-self: start;
}

...wenn sie mit dem Schlüsselwort flip-block gedreht wird, ergibt sich Folgendes

@try-position --custom-right {
  inset-area: bottom;
  align-self: end;
}

Demo

Spezifikation

Die Eigenschaft position-try-options ist im CSS Anchor Positioning Module Level 1-Entwurf definiert, der zum Zeitpunkt der Erstellung noch im Working-Draft-Status ist. Das bedeutet, dass sich vieles ändern kann, bis die Funktion eine formale Candidate Recommendation für die Implementierung wird.

Browser-Unterstützung

Data on support for the css-anchor-positioning feature across the major browsers from caniuse.com

Weitere Informationen und Tutorials