Van egy npm-csomag, amit hetente több mint 80 milliószor töltünk le azért, hogy ki tudjuk számolni: egy tooltip a gomb fölé vagy alá kerüljön-e. A @floating-ui/dom – a Popper.js utódja – az augusztus közepi héten 81,7 millió letöltésnél járt az npm statisztikája szerint, és akkor a rá épülő komponenskönyvtárakat még nem is számoltuk. Mindez egy olyan feladatra, ami definíció szerint layout: „tedd ezt a dobozt ahhoz a dobozhoz képest ide”. A layout pedig elvileg a böngésző munkaköri leírásának első sora.
Idén januárban, a Firefox 147-tel ez a történet lezárult: a CSS anchor positioning mindhárom nagy böngészőmotorban ott van. Nem kísérleti játékszer – a Chrome 2024 májusa óta szállítja, a Safari tavaly szeptember óta –, úgyhogy ideje megnézni, mit vettünk eddig heti 80 millió letöltésért.

Miért kellett ehhez húsz évig JavaScript?
A position: absolute a containing blockhoz képest pozicionál, és ezen a láncon kívülre nem lát. A dropdownod viszont szinte sosem maradhat ott, ahol logikusan élne, a gomb mellett a DOM-ban: az útba eső overflow: hidden levágja, egy transform-os ős új containing blockot ránt alá, a z-index-háborúkról nem is beszélve. Ezért portalozzuk a body végére, újabban pedig a top layerbe tesszük popoverként vagy dialogként – a top layerről írtam korábban. Csakhogy onnan a gomb, amihez képest a helyét keresné, CSS-eszközökkel elérhetetlen volt: más a viszonyítási rendszere, és pont.
Maradt a getBoundingClientRect(), plusz scroll- és resize-listenerek, plusz újraszámolás mindenre, ami mozoghat. A Floating UI lényegében ezt csomagolja be (autoUpdate), és ad rá middleware-eket: offset, flip, shift. Kiforrott, korrekt munka – csak épp egy layoutfeladatot old meg a layoutmotoron kívülről, annak minden költségével együtt.
Név, kötés, hely
Az alapszereposztás három tulajdonság. Az anchor kap egy nevet, a pozicionált elem hivatkozik rá, aztán megmondod, hova kerüljön:
.mentes-gomb {
anchor-name: --mentes;
}
.tooltip {
position: fixed;
position-anchor: --mentes;
position-area: top;
margin-bottom: 8px;
}
Az anchor-name ugyanolyan dashed ident, mint a custom propertyk neve. A position-area pedig egy 3×3-as rácsban gondolkodik: az anchor a középső cella, a pozicionált elem a maradék nyolc cella (és a span-* kombinációk) bármelyikébe kérhető. A top itt azt jelenti: a felső sáv, az anchorhoz igazítva.
És itt jön az első mondat, amit JS-ből sosem kaptál ingyen: görgetésnél, átméretezésnél, layoutváltozásnál a böngésző magától viszi a tooltipet az anchorral együtt. Nincs listener, nincs autoUpdate, nincs elkésett frame, amiben a menü még a gomb régi helyén lebeg.
Ha a rács kevés, ott az anchor() függvény, amivel inset-tulajdonságokban hivatkozol az anchor széleire, és az anchor-size(), amivel a méretére:
.dropdown {
position: fixed;
position-anchor: --mentes;
top: calc(anchor(bottom) + 8px);
justify-self: anchor-center; /* vízszintesen az anchor közepén */
min-width: anchor-size(width); /* legalább olyan széles, mint a gomb */
}
A viewport széle – amiért a JS-t valójában fizettük
Az igazi munka sosem az volt, hogy a tooltip a gomb fölé kerüljön. Hanem az, hogy mi történjen, amikor a gomb a képernyő tetején van, és fölötte nincs hely. A Floating UI-ban ez a flip és a shift; CSS-ben a position-try-fallbacks:
.tooltip {
position: fixed;
position-anchor: --mentes;
position-area: top;
position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
}
A böngésző sorban végigpróbálja az opciókat, és az elsőt alkalmazza, amelyikkel az elem nem lóg ki a viewportból; ha egyik sem jó, marad az eredeti pozíció. A flip-block a blokktengely mentén tükröz (fölülről alulra), a flip-inline vízszintesen, a kettő együtt átlósan. Ha ez kevés, a @position-try at-rule-lal saját fallback-pozíciókat definiálhatsz eltérő margókkal és méretezéssel, a position-visibility: anchors-visible pedig el is rejti a tooltipet, amikor az anchor kigörög a képből. Ez utóbbi a spec legfrissebb rétege: 2026 januárja óta számít mindenhol elérhetőnek.
A kedvenc részem: nulla konfiguráció
A Popover API-val kombinálva a dolog már-már gyanúsan kényelmes. A popovertarget attribútum ugyanis implicit anchor-kapcsolatot hoz létre a gomb és a popover között – se anchor-name, se position-anchor nem kell:
<button popovertarget="muveletek">Műveletek</button>
<div id="muveletek" popover>…</div>
[popover] {
/* a popover UA-stílusa (inset: 0; margin: auto) középre tenné */
inset: auto;
margin: 0;
position-area: bottom span-right;
position-try-fallbacks: flip-block;
}
Az eredmény egy dropdown, ami a top layerben él (semmi nem takarja ki, az ősök overflow-ja nem érdekli), a gombhoz tapad, Esc-re és háttérkattintásra záródik, a viewport szélénél átfordul – nulla sor JavaScripttel. Ezen a ponton a megszokott „npm-csomag kell egy legördülő menühöz” felállás kezd elég nehezen védhető lenni.
Apróbetűs rész
- Ha több elem kapja ugyanazt az
anchor-name-et, a DOM-sorrendben utolsó nyer. Ismétlődő komponenseknél – lista, ahol minden sornak saját menüje van – ez elsőre meglepetés; azanchor-scopetulajdonsággal korlátozható a név a komponens részfájára. - Csak
absolutevagyfixedpozicionálású elemre működik – aposition-anchorönmagában nem csinál semmit. - A szintaxis menet közben változott: az
inset-area-bólposition-arealett, aposition-try-options-bólposition-try-fallbacks– a Chrome 129 óta már az új nevek élnek. A 2024-es tutorialok (és az azokon tanult AI-válaszok) egy része ezért ma is halott szintaxist mutat. - A kapcsolat tisztán vizuális: fókuszsorrendről,
aria-expanded-ről továbbra is te gondoskodsz. Az anchor positioning a Floating UI-t váltja ki, nem az akadálymentesítést. - Elemhez tudsz horgonyozni, ponthoz nem: az egérpozíciónál nyíló context menühöz vagy a szövegkijelöléshez tapadó buborékhoz marad a JS (a Floating UI-ban ezek a virtual elementek).
Használnám-e productionben?
A támogatási sor: Chrome és Edge 125 (2024. május), Safari 26 (2025. szeptember), Firefox 147 (2026. január 13.). Vagyis friss Baseline – ami azt is jelenti, hogy egy tavalyi Safari vagy a jelenlegi, vállalati gépeken tipikus Firefox ESR 140 még semmit nem tud belőle.
Belső adminon, kontrollált böngészőflottán: igen, azonnal, gondolkodás nélkül. Publikus felületen árnyaltabb a kép. Tooltipnél az elegáns út a progresszív: @supports (anchor-name: --a) mögött anchor positioning, alatta egy egyszerű, fixen elhelyezett fallback – egy rossz helyen felugró tooltip bosszantó, nem tragédia. Ahol viszont a pozicionálás funkcionális – navigációs dropdown, date picker –, ott vagy marad még egy darabig a Floating UI, vagy ott az OddBird polyfillje; utóbbi korrekt munka, de a korlátait (nincs position-try-order, RTL-lel és vertikális írásmóddal nem boldogul) érdemes elolvasni, mielőtt ráépülsz.
A heti 80 millió letöltés nem fog eltűnni jövő keddre: a React-ökoszisztéma tele van Floating UI-ra épülő komponenskönyvtárral, és azok lassan mozdulnak. De új projektben ma már az a kérdés, hogy miért kellene JavaScript egy tooltipnek, nem az, hogy hogyan. Húsz év után a „hova kerüljön ez a doboz ahhoz képest” végre ott dől el, ahol mindig is kellett volna: a layoutmotorban.
Források
- MDN: Using CSS anchor positioning
- MDN: Fallback options and conditional hiding for overflow
- CSSWG: CSS Anchor Positioning Module Level 1
- Chrome for Developers: Introducing the CSS anchor positioning API
- WebKit: WebKit Features in Safari 26.0
- Firefox 147.0 release notes
- OddBird: CSS Anchor Positioning Polyfill