Abschnitt 15 · Lektion 5
Ankerpositionierung
position: absolute sucht sich den nächsten positionierten Vorfahren und richtet sich an dessen Kanten aus, so wie in Lektion 8.3. Das ist eine harte Bedingung. Willst du einen Tooltip an einen Button hängen, musst du eine Hülle um den Button legen. Und soll er an einem Element in einer Tabellenzelle hängen, hast du ein Problem.
Ankerpositionierung dreht das um. Das Bezugselement bekommt einen Namen, und das schwebende Element nennt diesen Namen. Wo die beiden im Baum stehen, ist egal.
Zwei Eigenschaften, ein Name
<p>Ein Absatz davor, damit man die Lage sieht.</p>
<button class="button" type="button">Was ist das?</button>
<span class="tooltip">Hängt am Button, nicht am Elternteil.</span> body {
margin: 0;
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.button {
/* Der Button bekommt einen Namen. */
anchor-name: --button;
padding: 8px 16px;
border: 0;
border-radius: 8px;
font: inherit;
color: #ffffff;
background-color: #2563eb;
}
.tooltip {
/* Das schwebende Element nennt den Namen und
sagt, an welcher Seite es liegen soll. */
position: absolute;
position-anchor: --button;
position-area: block-end span-inline-end;
margin-top: 8px;
width: max-content;
max-width: 220px;
padding: 8px 16px;
border-radius: 8px;
font-size: 14px;
color: #fafafa;
background-color: #18181b;
} anchor-name: --button steht am Bezugselement. Der Name ist ein selbst gewählter Bezeichner mit zwei Bindestrichen davor, genau wie bei Custom Properties. Sonst hat er mit ihnen nichts zu tun.
position-anchor: --button am schwebenden Element nennt den Anker, an dem es hängt. Dazu braucht es weiterhin position: absolute oder fixed, denn schweben muss es trotzdem.
Die beiden Namen stehen nicht im Auskunftsstreifen, dort stehen Layout, Farben und Schrift. Am Tooltip findest du position: absolute und width: 220px, das ist die eine Hälfte. Die andere bekommst du in der Eingabezeile der Console. getComputedStyle(document.querySelector('.button')).anchorName antwortet mit --button und getComputedStyle(document.querySelector('.tooltip')).positionAnchor mit demselben Namen. Ob der Browser überhaupt mitmacht, verrät CSS.supports('anchor-name', '--x'), und das ist @supports als Frage statt als Block.
<p>Ein Absatz davor, damit man die Lage sieht.</p>
<button class="button" type="button">Was ist das?</button>
<span class="tooltip">Sollte unter dem Button hängen.</span> body {
margin: 0;
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.button {
/* So nicht: der Name ohne die zwei Striche. Das ist
kein gültiger Wert, und die Zeile fällt weg. */
anchor-name: button;
padding: 8px 16px;
border: 0;
border-radius: 8px;
font: inherit;
color: #ffffff;
background-color: #2563eb;
}
.tooltip {
position: absolute;
position-anchor: button;
position-area: block-end span-inline-end;
margin-top: 8px;
width: max-content;
max-width: 220px;
padding: 8px 16px;
border-radius: 8px;
font-size: 14px;
color: #fafafa;
background-color: #18181b;
} Im Beispiel fehlen die beiden Striche an beiden Stellen, anchor-name: button und position-anchor: button. Ohne sie ist ein Name kein gültiger Wert, und der Browser verwirft beide Zeilen. Der Tooltip hängt dann nicht unter dem Button. Er liegt auf seiner Höhe daneben, ungefähr dort, wo er ohne jede Angabe im Textfluss stünde. Firefox schiebt ihn dabei noch ein Stück über die rechte Kante des Buttons. In der Eingabezeile der Console siehst du es auch, denn anchorName antwortet am Button mit none.
Mit position-area legst du dann fest, wo genau. Dahinter steckt ein Raster aus neun Feldern rund um den Anker. block-start ist oben, block-end unten, inline-start und inline-end sind links und rechts, und span-inline-end heißt “und von dort nach rechts ausdehnen”. Brauchst du es genauer, rechnest du mit anchor() in top, left und den anderen Verschiebungen einzelne Werte aus.
<p>Ein Absatz davor, damit man die Lage sieht.</p>
<span class="huelle">
<button class="button" type="button">Was ist das?</button>
<span class="tooltip">Braucht die Hülle drumherum.</span>
</span> body {
margin: 0;
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
/* Ohne diese zusätzliche Hülle geht es nicht: Der
Bezugsrahmen muss ein Vorfahr sein. */
.huelle {
position: relative;
display: inline-block;
}
.button {
padding: 8px 16px;
border: 0;
border-radius: 8px;
font: inherit;
color: #ffffff;
background-color: #2563eb;
}
.tooltip {
position: absolute;
top: 100%;
left: 0;
margin-top: 8px;
width: max-content;
max-width: 220px;
padding: 8px 16px;
border-radius: 8px;
font-size: 14px;
color: #fafafa;
background-color: #18181b;
} Die beiden Fassungen sehen gleich aus, der Unterschied steht im HTML. Die zweite braucht eine zusätzliche Hülle, die es nur gibt, damit CSS einen Bezugsrahmen hat. Das ist Markup ohne Bedeutung, und davon sammelt eine Seite im Lauf der Zeit einiges an.
Der Anker muss kein Vorfahre sein
<header class="kopf">
<button class="button" type="button">Konto</button>
</header>
<main>
<p>Der Inhalt der Seite.</p>
<p>Noch ein Absatz.</p>
</main>
<footer class="fuss">
<p>Ganz unten im Markup steht das Menü.</p>
<div class="menue">Es hängt trotzdem am Button oben.</div>
</footer> body {
margin: 0;
padding: 24px;
font-family: system-ui, sans-serif;
line-height: 1.5;
}
.kopf {
padding-bottom: 16px;
border-bottom: 1px solid #d4d4d8;
}
.button {
anchor-name: --konto;
padding: 8px 16px;
border: 0;
border-radius: 8px;
font: inherit;
color: #ffffff;
background-color: #2563eb;
}
.fuss {
margin-top: 24px;
color: #52525b;
font-size: 14px;
}
.menue {
position: absolute;
position-anchor: --konto;
position-area: block-end span-inline-end;
margin-top: 8px;
width: 200px;
padding: 16px;
border-radius: 8px;
font-size: 14px;
color: #18181b;
background-color: #f4f4f5;
box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
} Hier steht das Menü ganz unten im Dokument und der Button ganz oben, und trotzdem hängt das Menü am Button. Mit position: absolute ist das schlicht nicht zu machen.
Praktisch wird das überall dort, wo das schwebende Element aus dem Fluss heraus muss, weil ein Vorfahre overflow: hidden hat. Ein Tooltip in einer scrollbaren Liste war bisher deshalb ein Fall für JavaScript. Man hat ihn an das Ende des Dokuments gehängt und seine Position bei jedem Scrollen neu ausgerechnet. Jetzt hängt er einfach am Anker.
Am Rand von selbst umklappen
Der zweite Grund für die Bibliotheken war der Bildschirmrand. Ein Tooltip, der rechts unten liegen soll, muss links oben liegen, wenn rechts unten kein Platz mehr ist.
position-try-fallbacks nimmt eine Liste von Ausweichlagen, und der Browser probiert sie der Reihe nach durch, bis eine passt. Für die häufigen Fälle gibt es fertige Werte wie flip-block und flip-inline, die die gewählte Lage einfach spiegeln. Zusammen mit dem popover-Attribut aus dem HTML-Kurs hast du so einen Tooltip zum Anklicken, und zwar ohne eine einzige Zeile JavaScript.
Erst nachsehen, dann benutzen
Ankerpositionierung ist gerade erst überall angekommen. Alle drei großen Browser können sie, Firefox als letzter seit Januar 2026. Sie ist also neu. Soll deine Seite auch auf einem zwei Jahre alten Gerät funktionieren, kannst du dich nicht darauf verlassen.
Damit ist sie ein Musterfall für Lektion 15.1. Erst kommt die Fassung, die überall läuft, dann @supports (anchor-name: --a) und darin die bessere. Der Fallback kostet nur die Hülle, die es sowieso schon gab, und dafür funktioniert die Seite in jedem Browser, auch in einem, der von Ankern noch nie etwas gehört hat. So ist auch die Aufgabe gebaut, dort mit anchor() statt position-area, und warum, steht im Aufgabentext.
Zum Mitnehmen
Ankerpositionierung richtet ein Element an einem anderen aus, ohne dass die beiden im Markup etwas miteinander zu tun haben. Der Anker bekommt mit anchor-name einen Namen mit zwei Strichen davor, das schwebende Element nennt ihn in position-anchor.
Jetzt du
Basis Konto, kostenlosZu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.
Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.
Was in dieser Lektion steckt
-
Artikel mit 4 Beispielen zum Ausprobieren
Steht hier, ohne Konto lesbar.
-
Aufgabe im Editor, direkt im Browser geprüft
Öffnet sich mit dem Basis Konto.