Wenn Sie Tooltips oder Popovers mit der CSS-Ankerpositionierung erstellen, kann der Browser das Element automatisch in eine Fallback-Position „umdrehen“, wenn es sonst den Darstellungsbereich überschreiten würde. In diesem Fall können Sie den Stil des positionierten Inhalts anpassen, z. B. um einen Pfeil, der vom positionierten Inhalt zum Anker zeigt, neu zu positionieren.
Verankerte Containerabfragen lösen dieses Problem, indem sie es ermöglichen, den aktiven Positionierungsstatus eines Elements abzufragen und entsprechende Stile anzuwenden. Allgemeine Informationen zur Positionierung von verankerten Drop-downs und Flyouts mit Viewport-Kollisionsumkehr (ohne Neugestaltung des Richtungspfeils) finden Sie unter Viewport-Aware Dropdowns.
Das Problem
Stellen Sie sich eine Kurzinfo vor, die standardmäßig über ihrem Anker angezeigt wird. Unten befindet sich ein Abwärtspfeil. Wenn der Nutzer scrollt und der Kurzinfo-Text unter dem Anker erscheint, zeigt der Pfeil jetzt in die falsche Richtung und befindet sich auf der falschen Seite des Kurzinfo-Texts.
Die Lösung: Verankerte Containerabfragen
Wenn Sie container-type: anchored für das positionierte Element festlegen, wird es zu einem Abfragecontainer, der seinen eigenen ankerpositionierten Zustand kennt. Anschließend können Sie die @container anchored()-Abfrage verwenden, um die untergeordneten Elemente oder Pseudoelemente zu aktualisieren.
1. Kurzinfo und Trigger erstellen
Erstellen Sie einen Kurzinfo mit der Popover API. Durch das Aufrufen des Popovers über popovertarget wird automatisch eine implizite Ankerverbindung mit dem Trigger-Button hergestellt. Es ist also kein explizites anchor-name oder position-anchor erforderlich.
<button popovertarget="tooltip" id="anchor" aria-describedby="tooltip">anchor</button>
<div id="tooltip" popover role="tooltip"></div>
Setzen Sie die Popover-Inset- und Randstile für die Verwendung mit der Ankerpositionierung zurück, aber nur, wenn die Ankerpositionierung unterstützt wird.
@supports (anchor-name: --my-anchor) {
[popover] {
inset: auto;
margin: unset;
}
}
2. Container einrichten
Wenden Sie container-type: anchored auf das zu positionierende Element an. Für dieses Element muss auch position-try-fallbacks definiert sein, damit das Umdrehen möglich ist.
#tooltip {
position: fixed;
position-area: block-start;
position-try-fallbacks: flip-block;
/* Enable anchored container queries */
container-type: anchored;
}
3. Stil basierend auf dem Fallback
Mit @container anchored(fallback: <value>) können Sie Stile anwenden, wenn ein bestimmter Fallback aktiv ist.
Wie bei allen Containerabfragen können mit @container nur untergeordnete Elemente des Containers formatiert werden. Eine gängige Strategie zum Erstellen der Pfeile ist die Verwendung der Pseudoelemente ::before und ::after, die als untergeordnete Elemente behandelt und direkt formatiert werden können. Um den Kurzinfo-Text selbst zu gestalten (wie in Schritt 4 gezeigt), fügen wir der Kurzinfo ein untergeordnetes Element hinzu und erstellen den Pfeil in seinem Pseudoelement ::before.
<div id="tooltip" popover role="tooltip">
<div class="tooltip-content">Tooltip</div>
</div>
.tooltip-content::before {
/* Default "down" arrow for the 'top' position */
content: "▼";
position: absolute;
inset-block-end: 0;
inset-inline-start: 1rem;
}
/* Update to an "up" arrow when the 'flip-block' fallback (bottom) is active */
@container anchored(fallback: flip-block) {
.tooltip-content::before {
content: "▲";
inset-block-start: 0;
inset-block-end: auto;
}
}
4. Container selbst gestalten
Wenn Sie beim Umdrehen des Containers Eigenschaften des Containers selbst ändern müssen (z. B. margin oder background-color), sollten Sie ein inneres Wrapper-Element verwenden.
- Wenden Sie
container-type: anchoredauf das äußere positionierte Element an. - Sprechen Sie das innere Element im
@container-Block an.
@container anchored(fallback: flip-block) {
.tooltip-content {
border-radius: 0 0 .5rem .5rem;
margin-block-start: 0.25rem;
}
}
Best Practices
- Logische Fallbacks bevorzugen: Verwenden Sie Keywords wie
flip-blockundflip-inlineinposition-try-fallbacksfür einfachere Abfragen, die RTL und verschiedene Schreibmodi automatisch verarbeiten. - Pseudoelemente für Pfeile verwenden: Tooltip-Pfeile sind rein dekorativ und eignen sich perfekt für
::beforeoder::after. Sie können über verankerte Containerabfragen ohne zusätzliches DOM gestaltet werden.
Fallback-Strategien
Die Positionierung des Pfeils basierend auf dem angewendeten Fallback ist eine progressive Verbesserung. Es gibt keine andere Möglichkeit, auf die Fallback-Position zu reagieren. Wenn Sie den Pfeil in Browsern ausblenden möchten, die keine Containerabfragen für die Ankerposition unterstützen, prüfen Sie die CSS-Unterstützung mit @supports (container-type: anchored).
@supports (container-type: anchored) {
.tooltip-content::before {
content: "▼";
}
}
Fallbacks und Browserunterstützung für Popover
Die Popover API ist größtenteils eine progressive Verbesserung, aber ihre definierenden Verhaltensweisen – die Platzierung auf der obersten Ebene, das Schließen durch Klicken außerhalb des Popovers und der Aufruf von popovertarget – haben kein CSS-Äquivalent. Ältere Browser benötigen ein Polyfill oder ein manuelles Fallback, wenn Sie kein Polyfill bereitstellen möchten.
Polyfill: Damit das Attribut popover in älteren Browsern unterstützt wird, lade @oddbird/popover-polyfill bedingt. OBLIGATORISCH: Prüfe, ob die Funktion unterstützt wird, indem du nach der Property popover in HTMLElement.prototype suchst, und lade das Polyfill nur, wenn die native Unterstützung fehlt. Lade es NICHT bedingungslos.
Mit einem Bundler oder einer Importzuordnung:
// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
import("@oddbird/popover-polyfill");
}
Ohne Bundler importieren Sie aus einem CDN in einem <script type="module">:
<script type="module">
if (!("popover" in HTMLElement.prototype)) {
import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
}
</script>
Einschränkung beim Styling: Das Polyfill kann die echte Pseudoklasse :popover-open nicht definieren, daher wird stattdessen die Klasse .\:popover-open angewendet. OBLIGATORISCH: Kombinieren Sie die beiden mit :is() oder :where(). Andernfalls verwerfen Browser, die :popover-open nicht unterstützen, die gesamte Regel:
[popover]:is(:popover-open, .\:popover-open) {
display: block;
}
Alternativ können Sie für einen Legacy-Fallback ohne Polyfill position: fixed verwenden und die Koordinaten manuell über getBoundingClientRect() berechnen oder die Standardpositionierung mit inset: auto verwenden, wenn das für den Anwendungsfall akzeptabel ist.
Browser, die die Popover API nicht unterstützen, unterstützen auch die Ankerpositionierung nicht. Daher wird die Kurzinfo in der Mitte des Bildschirms angezeigt.