Appearance
CSS Anchor Positioning
Native browser positioning for tooltips, dropdowns, and context menus that automatically stay in viewport without JavaScript calculations.
When to use
Use CSS anchor positioning for any floating UI — tooltips, dropdown menus, context menus — that needs to stay attached to a trigger element and automatically flip or reposition when near viewport edges, all without JavaScript calculations.
The pattern
Basic positioning
An element declares itself as an anchor with anchor-name, and a positioned element attaches to it with position-anchor. The anchor() function places edges relative to the anchor, and position-try-fallbacks flips the element when it would overflow the viewport.
css
/* Anchor element */
[data-tooltip] {
anchor-name: --tooltip-anchor;
}
/* Positioned element */
[data-tooltip]::after {
content: attr(data-tooltip);
position: absolute;
position-anchor: --tooltip-anchor;
/* Position above, center-aligned */
bottom: anchor(top);
left: anchor(center);
translate: -50% -8px;
/* Auto-flip to bottom if no room */
position-try-fallbacks: flip-block;
}Tooltip with custom dwell time
A tooltip that waits 500ms before appearing on hover but shows immediately on keyboard focus uses a CSS animation delay instead of JavaScript timers. The forwards fill mode keeps the tooltip visible after the animation completes.
html
<button data-tooltip="Delete this item">🗑</button>
<style>
[data-tooltip]::after {
opacity: 0;
transition: opacity 200ms;
}
[data-tooltip]:hover::after {
animation: tooltip-show 200ms 500ms forwards;
}
[data-tooltip]:focus::after {
opacity: 1; /* Immediate for keyboard users */
}
@keyframes tooltip-show {
to { opacity: 1; }
}
</style>Position functions
anchor(top)— Top edge of anchoranchor(bottom)— Bottom edgeanchor(left)— Left edgeanchor(right)— Right edgeanchor(center)— Center point
Fallbacks
flip-block— Flip vertical positionflip-inline— Flip horizontal positionflip-block flip-inline— Flip both
Trade-offs
- Browser support. CSS Anchor Positioning is supported in Chrome 125+, Edge 125+. Use
@supports (anchor-name: --test)for feature detection.