CSS Anchor Positioning Kills the Tooltip Library
Most tooltip libraries ship between 40 and 80 kB of JavaScript to solve a problem CSS has had an answer to since 2023. That problem: positioning one element relative to another element that isn't its parent.
How it works
Three CSS properties handle the whole thing. anchor-name marks the reference element with a custom identifier. position-anchor connects the floating element to it. anchor() reads the reference element's edges to compute offsets.
.trigger {
anchor-name: --my-tooltip;
}
.tooltip {
position: absolute;
position-anchor: --my-tooltip;
top: anchor(bottom);
left: anchor(center);
translate: -50% 8px;
}What you were doing before
Before this, you'd call getBoundingClientRect() on the trigger, add scroll offsets, check viewport edges, and set top and left in a useEffect. Libraries like Floating UI automate that calculation. The calculation was always the wrong abstraction.
const rect = trigger.getBoundingClientRect();
setPosition({
top: rect.bottom + window.scrollY + 8,
left: rect.left + window.scrollX + rect.width / 2,
});Floating UI is well-built. You shouldn't need it for tooltips.
Browser support
Anchor positioning has full support in Chrome 125+ and Firefox 130+. Safari ships it in Safari 18.4. For older Safari, the @oddbird/css-anchor-positioning polyfill covers the spec with a 12 kB footprint, cheaper than the library it replaces.
When to use it
Use anchor positioning for tooltips, popovers, dropdowns, and any UI where one element needs to track another without JavaScript. Skip it when you need collision detection across nested scroll containers; Floating UI still handles that better.