Fertige Rezepte für Dropdown-Menüs und Tooltips, die nie über den Rand hinausragen
Über die eingebauten Kurzformen wie flip-block hinaus lassen sich mit @position-try eigene, benannte Fallback-Positionen definieren, komplett mit eigenem Innenabstand zum Viewport-Rand. Dieser Artikel zeigt fertige, kopierbare Rezepte für Dropdown-Menüs, verschachtelte Untermenüs und Tooltips, die zuverlässig innerhalb des sichtbaren Bereichs bleiben.
Inhaltsverzeichnis
- 1. Warum Menüs andere Anforderungen haben als einfache Tooltips
- 2. Die Syntax von @position-try: welche Eigenschaften erlaubt sind
- 3. Sicherheitsabstand zum Viewport-Rand einbauen
- 4. Rezept: Dropdown-Menü, das nie über den Rand hinausragt
- 5. Rezept: Tooltip mit an den Anker gekoppelter Breite
- 6. Verschachtelte Untermenüs mit eigener Anker-Kette
- 7. Anchor Positioning innerhalb scrollbarer Container
- 8. Häufige Fallstricke bei eigenen Position-Try-Rezepten
- 9. Checkliste vor dem Ausliefern eines Menü- oder Tooltip-Rezepts
- 10. Zusammenfassung
- 11. FAQ
1. Warum Menüs andere Anforderungen haben als einfache Tooltips
Ein Dropdown-Menü darf niemals über den Bildschirmrand hinausragen, weil abgeschnittene Menüpunkte nicht nur unschön aussehen, sondern schlicht unbedienbar werden. Anders als ein reines Info-Tooltip, das im Zweifel auch mal etwas ungünstig sitzt, muss ein Menü jeden einzelnen seiner Einträge vollständig klickbar halten, was die Anforderungen an die Fallback-Logik deutlich erhöht.
Die eingebauten Kurzformen flip-block und flip-inline reichen für viele Tooltip-Fälle aus, stoßen bei Menüs aber an Grenzen, sobald zusätzlicher Innenabstand zum Viewport-Rand, eine Mindestbreite oder eine an die Anker-Breite gekoppelte Ausrichtung gebraucht wird. Genau dafür existiert die @position-try-Regel: Sie erlaubt es, eine komplette, benannte Position mit allen nötigen Zusatzeigenschaften einmal zu definieren und in beliebig vielen Komponenten wiederzuverwenden.
2. Die Syntax von @position-try: welche Eigenschaften erlaubt sind
Eine @position-try-Regel wird mit einem selbst gewählten Namen im --dashed-ident-Format deklariert und enthält innerhalb der geschweiften Klammern eine Teilmenge der Positionierungs-Eigenschaften: position-area oder die einzelnen inset-Werte, margin, width und height sowie self-alignment-Eigenschaften wie justify-self. Layout-fremde Eigenschaften wie Farben oder Schriftarten sind hier bewusst nicht erlaubt, weil die Regel ausschließlich für Positionierung gedacht ist.
Diese Beschränkung sorgt dafür, dass eine @position-try-Regel klar von der visuellen Gestaltung der Komponente getrennt bleibt. Das Menü selbst bekommt seine Hintergrundfarbe, seinen Schatten und seine Border ganz normal über die Klassenregel, während die @position-try-Regel ausschließlich für die räumliche Alternative zuständig ist. Diese Trennung macht es leicht, dieselbe visuelle Komponente an unterschiedlichen Stellen der Seite mit unterschiedlichen Fallback-Positionen wiederzuverwenden.
3. Sicherheitsabstand zum Viewport-Rand einbauen
Ein Menü, das direkt an den Bildschirmrand stößt, wirkt gequetscht und ist auf Touch-Geräten schwerer zu treffen. Innerhalb einer @position-try-Regel lässt sich dieser Abstand mit margin oder expliziten inset-Werten festlegen, kombiniert mit calc(), um einen festen Mindestabstand unabhängig von der Fenstergröße zu garantieren.
Für besonders robuste Menüs bietet sich zusätzlich eine feste max-width in Kombination mit width: max-content an, damit lange Menüpunkte nicht dafür sorgen, dass das Menü über den durch die @position-try-Regel definierten Sicherheitsabstand hinauswächst. So bleibt garantiert, dass selbst der ungünstigste Fallback-Fall noch innerhalb des sichtbaren Bereichs Platz findet.
@position-try --menu-safe-bottom {
position-area: bottom span-right;
margin-block-start: 0.5rem;
margin-inline-end: max(1rem, env(safe-area-inset-right));
max-width: min(20rem, calc(100vw - 2rem));
}
4. Rezept: Dropdown-Menü, das nie über den Rand hinausragt
Das folgende Rezept kombiniert einen Trigger-Button mit einem über popover geöffneten Menü. Zwei benannte @position-try-Regeln decken die Fälle ab, in denen der Button in der rechten oder unteren Bildschirmhälfte sitzt, jeweils mit demselben Sicherheitsabstand zum Rand, den der vorherige Abschnitt eingeführt hat.
Wichtig ist die Reihenfolge in position-try-fallbacks: Zuerst die Variante, die horizontal spiegelt, dann die, die zusätzlich vertikal spiegelt, damit das Menü in der ungünstigsten Bildschirmecke immer noch eine sinnvolle Position findet, statt einfach auf die zuletzt geprüfte Alternative zurückzufallen.
<button popovertarget="user-menu" style="anchor-name: --user-trigger;">
Konto
</button>
<ul id="user-menu" popover class="menu">
<li><a href="/profil">Profil</a></li>
<li><a href="/einstellungen">Einstellungen</a></li>
<li><a href="/logout">Abmelden</a></li>
</ul>
<style>
@position-try --menu-flip-left {
position-area: bottom span-left;
margin-block-start: 0.5rem;
}
@position-try --menu-flip-top {
position-area: top span-left;
margin-block-end: 0.5rem;
}
.menu {
position: absolute;
position-anchor: --user-trigger;
position-area: bottom span-right;
margin-block-start: 0.5rem;
min-width: anchor-size(width);
position-try-fallbacks: --menu-flip-left, --menu-flip-top;
}
</style>
5. Rezept: Tooltip mit an den Anker gekoppelter Breite
Ein Tooltip soll oft nicht breiter werden als sein Auslöser-Element, damit es sich optisch ruhig in ein Formular oder eine Tabellenzeile einfügt. Die Funktion anchor-size() liest die Breite oder Höhe des Ankers aus und lässt sich direkt in width, min-width oder max-width des Tooltips einsetzen, unabhängig davon, welche Fallback-Position gerade aktiv ist.
Kombiniert mit einer @position-try-Regel, die zusätzlich eine feste max-width als obere Grenze setzt, bleibt das Tooltip auch dann lesbar, wenn der Anker selbst sehr breit ist, etwa eine ganze Tabellenzeile. So verhindert die Kombination aus anchor-size() und expliziter Obergrenze, dass ein Tooltip in beide Extreme kippt, zu schmal für den Text oder unangenehm breit für ein einzelnes Wort.
@position-try --tooltip-capped {
position-area: top;
margin-block-end: 0.4rem;
max-width: 22rem;
}
.field-tooltip {
position: absolute;
position-anchor: --field-trigger;
position-area: top;
min-width: anchor-size(width);
max-width: min(anchor-size(width, 1.5), 22rem);
position-try-fallbacks: --tooltip-capped, flip-block;
}
6. Verschachtelte Untermenüs mit eigener Anker-Kette
Ein Untermenü, das beim Hover oder Klick auf einen Menüpunkt aufklappt, braucht seinen eigenen anchor-name auf dem jeweiligen Menüpunkt und seine eigene, unabhängige position-try-fallbacks-Kette. Wichtig ist, dass jeder Menüpunkt, der ein Untermenü öffnen kann, einen eindeutigen Anker-Namen bekommt, etwa dynamisch generiert, damit sich mehrere gleichzeitig offene Untermenüs nicht gegenseitig überschreiben.
Für die Fallback-Kette eines Untermenüs bietet sich standardmäßig right als bevorzugte Position an, mit flip-inline als erstem Fallback, damit ein Untermenü, das am rechten Bildschirmrand aufgeklappt würde, automatisch nach links wechselt. Diese Logik funktioniert unabhängig von der Position des übergeordneten Menüs, weil jede Anker-Beziehung für sich betrachtet wird.
7. Anchor Positioning innerhalb scrollbarer Container
Sitzt der Anker nicht direkt im Viewport, sondern in einem scrollbaren Container wie einer Tabelle mit fixierter Höhe, bezieht sich die Fallback-Logik standardmäßig auf den nächsten passenden Containing Block, nicht zwingend auf den gesamten Viewport. Das ist in den meisten Fällen genau das gewünschte Verhalten, weil ein Tooltip innerhalb einer scrollbaren Tabelle nicht über deren Rand hinausragen soll, selbst wenn im restlichen Viewport noch Platz wäre.
Wird stattdessen ausdrücklich gewünscht, dass sich ein Element am gesamten Viewport orientiert statt am umgebenden Scroll-Container, hilft die Eigenschaft position: fixed in Kombination mit Anchor Positioning, weil sie den Containing Block explizit auf den initial containing block anhebt. Diese Unterscheidung sollte bei jeder Komponente bewusst getroffen werden, statt sich auf das jeweilige Default-Verhalten zu verlassen.
8. Häufige Fallstricke bei eigenen Position-Try-Rezepten
Ein häufiger Fehler ist ein doppelt vergebener anchor-name: Zeigen zwei verschiedene Elemente auf denselben Namen, bindet sich das positionierte Element an das zuletzt im Dokument stehende. Das führt zu scheinbar zufälligem Fehlverhalten, das sich nur schwer nachvollziehen lässt, solange man nicht gezielt nach doppelten Namen sucht.
Ein zweiter Stolperstein ist, position-try-fallbacks auf einem Element zu setzen, das selbst keinen position-anchor referenziert und nicht absolut oder fixiert positioniert ist. Ohne diese Voraussetzung ignoriert der Browser die gesamte Fallback-Kette stillschweigend, ohne eine Fehlermeldung auszugeben, was die Fehlersuche in der Praxis unnötig erschwert.
9. Checkliste vor dem Ausliefern eines Menü- oder Tooltip-Rezepts
Vor dem produktiven Einsatz lohnt sich ein kurzer, aber systematischer Test jeder Komponente an allen vier Bildschirmrändern, mit langem und kurzem Textinhalt sowie in einem schmalen mobilen Viewport. Wer diese Kombinationen einmal in einer Checkliste festhält, kann sie bei jeder neuen Komponente wiederverwenden, statt bei jedem Projekt erneut alle Randfälle einzeln zu entdecken.
Ebenso wichtig ist ein Blick auf die tatsächliche Tastatur- und Screenreader-Bedienung, weil die räumliche Fallback-Position rein visuell ist und nichts an der Fokus-Reihenfolge ändert. Ein Menü, das visuell perfekt positioniert ist, aber per Tastatur nicht erreichbar ist, hat sein eigentliches Ziel trotzdem verfehlt.
| Rezept-Baustein | CSS-Eigenschaft | Zweck |
|---|---|---|
| Sicherheitsabstand zum Rand | margin mit calc() in @position-try |
Menü stößt nie direkt an den Viewport-Rand |
| Breite an Anker koppeln | anchor-size(width) in min-width/max-width |
Tooltip wird nicht schmaler oder viel breiter als sein Auslöser |
| Eindeutige Untermenü-Anker | Dynamisch generierter anchor-name pro Menüpunkt |
Mehrere gleichzeitig offene Untermenüs überschreiben sich nicht |
| Viewport statt Scroll-Container | position: fixed statt position: absolute |
Positionierung bezieht sich auf den gesamten Viewport |
| Fallback-Voraussetzung prüfen | position-anchor plus position: absolute/fixed |
Verhindert stillschweigend ignorierte Fallback-Ketten |
Mironsoft
Modernes CSS, Layout-Architektur und Rendering-Performance
CSS, das wartbar bleibt statt mit jeder Änderung zu brechen?
Wir prüfen bestehende Stylesheets auf Spezifitäts-Chaos und Layout-Thrashing und bauen daraus eine CSS-Architektur mit Cascade Layers, Custom Properties und modernen Layout-Primitiven, die auch nach dem zehnten Feature noch verständlich ist.
CSS-Audit
Spezifität, Cascade-Konflikte und ungenutzte Selektoren systematisch aufdecken.
Architektur-Refactoring
Cascade Layers, Custom Properties und Design Tokens sauber einführen.
Performance-Tuning
Layout-Thrashing, teure Selektoren und Rendering-Engpässe gezielt beheben.
10. Zusammenfassung
Position-Try-Rezepte für Menüs und Tooltips: Das Wichtigste auf einen Blick
Eigene Fallback-Regeln
@position-try definiert benannte, wiederverwendbare Positionen mit eigenem Innenabstand, Breite und Ausrichtung.
Menü-Rezept
Zwei @position-try-Regeln mit horizontalem und vertikalem Flip decken jede Bildschirmecke robust ab.
Tooltip-Rezept
anchor-size() koppelt die Tooltip-Breite an den Anker, eine max-width verhindert unangenehm breite Tooltips.
Häufige Fehler
Doppelte anchor-name-Werte und fehlender position-anchor führen zu stillschweigend ignorierten Fallback-Ketten.