CSS Anchor Positioning lets you position any element relative to another element — its “anchor” — regardless of their location in the DOM. This eliminates the JavaScript needed for tooltips, dropdown menus, and popovers that must stay visually attached to a trigger element.
Problem: CSS tooltips and dropdown menus require JavaScript to position them relative to their trigger element — calculating offsets, handling viewport overflow, and updating position on scroll is complex boilerplate.
Solution: Use the CSS Anchor Positioning API — assign an anchor-name to the trigger element and reference it with position-anchor on the positioned element. Use anchor() and inset-area to declare the relative position declaratively, with position-try-fallbacks for automatic viewport overflow handling.
The examples below attach a tooltip to a button using anchor-name and position-anchor, position a dropdown relative to its trigger, and use position-try-fallbacks to automatically flip the tooltip when it would overflow the viewport.
/* 1. Mark the trigger element as an anchor */
.tooltip-trigger {
anchor-name: --my-tooltip; /* must start with -- like a custom property */
position: relative; /* not required, but good practice */
}
/* 2. Position the tooltip relative to its anchor */
.tooltip {
position: absolute; /* must be absolutely positioned */
position-anchor: --my-tooltip;
/* anchor() references edges of the anchor element:
anchor(top | right | bottom | left | center | start | end | %) */
bottom: calc(anchor(top) + 8px); /* 8px above the anchor's top edge */
left: anchor(center); /* horizontally centred on the anchor */
translate: -50% 0; /* fine-tune horizontal centring */
/* Prevent overflow: flip to below the anchor if no space above */
position-try-fallbacks: flip-block;
}
/* 3. Show only when the trigger is hovered or focused */
.tooltip {
opacity: 0;
transition: opacity 0.2s;
}
.tooltip-trigger:hover + .tooltip,
.tooltip-trigger:focus-visible + .tooltip {
opacity: 1;
}
Anchor positioning for a dropdown menu relative to its button:
/* Dropdown trigger */
.nav-item > button {
anchor-name: --nav-dropdown;
}
/* Dropdown panel — aligned to the left edge of the button, below it */
.dropdown-panel {
position: fixed; /* fixed allows positioning across stacking contexts */
position-anchor: --nav-dropdown;
top: anchor(bottom); /* top of panel = bottom of button */
left: anchor(left); /* align left edges */
min-width: anchor-size(width); /* at least as wide as the button */
/* Try right-align if overflowing right edge */
position-try-fallbacks: --dropdown-right-align;
}
@position-try --dropdown-right-align {
left: unset;
right: anchor(right);
}
/* Open/close via popover attribute (no JS needed for basic show/hide) */
/* */
/* ... */
.dropdown-panel:popover-open {
display: block;
}
NOTE: CSS Anchor Positioning is supported in Chrome 125+ and Safari 18.2+. Use the @supports (anchor-name: --test) at-rule to provide a JavaScript fallback for Firefox, which has the feature behind a flag as of late 2024.