Lesson 15 of 30
Positioning a tooltip against a trigger element that isn't its DOM parent used to mean a JS library recalculating pixel offsets on every scroll and resize. Anchor positioning lets the browser do it natively.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
Question 1 of 3
What links an anchor element to the element being positioned against it?
Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
A tooltip, dropdown, or popover almost never lives next to its trigger in the DOM — it's often rendered elsewhere entirely (at the end of the <body>, inside a portal) so it isn't clipped by an ancestor's overflow: hidden or trapped in the wrong stacking context. But it still needs to be positioned visually relative to that trigger, and CSS positioning (position: absolute, top, left) only ever worked relative to a positioned ancestor in the DOM tree — not an arbitrary unrelated element. That mismatch is exactly why JS positioning libraries like Popper or Floating UI exist: they measure the trigger's screen position with JavaScript, compute offsets, and re-run that computation on every scroll and resize to keep the tooltip attached.
CSS anchor positioning gives the browser this relationship natively, with no JavaScript recalculation:
anchor-name, set on the trigger element, names it as an anchor.position-anchor, set on the positioned element, points it at that anchor.top: anchor(bottom) then place the positioned element relative to a specific edge of its anchor — "align my top edge to the anchor's bottom edge," entirely computed by the browser's layout engine, not recalculated in JS on every scroll event.position-try adds fallback positions — if the browser detects the element would overflow the viewport in its primary position, it automatically tries an alternate position (e.g. flipping from below the trigger to above it), the same "flip when it would overflow" behavior JS libraries have always had to compute by hand..trigger-button {
anchor-name: --tooltip-anchor;
}
.tooltip {
position: absolute;
position-anchor: --tooltip-anchor;
top: anchor(bottom);
left: anchor(center);
position-try-fallbacks: flip-block;
}
.tooltip can live anywhere in the DOM — a sibling of <body>, deep in a portal, wherever avoids clipping — and still positions itself against .trigger-button's actual screen position, because the two are linked by name rather than by DOM nesting. position-try-fallbacks: flip-block tells the browser to flip the tooltip above the button automatically if placing it below would push it off-screen, without a resize or scroll listener anywhere in the code.
:has() or scroll snap in this same track, so pair any real usage with a @supports check and a JS-library fallback for browsers that don't understand it.anchor-name and position-anchor are a naming link, not a layout link — the anchor and the positioned element don't need to share any DOM relationship at all, which is the entire point, but it also means a typo in the custom name silently fails to connect them.position-try fallbacks are the native equivalent of "flip when it would overflow," a behavior every JS positioning library already computes by hand — knowing that parallel is what interviewers are usually listening for, more than syntax recall."How do positioning libraries like Popper or Floating UI actually keep a tooltip attached to its trigger?" is a real question, and being able to name that CSS is gaining a native equivalent — anchor positioning, with its own automatic overflow-flipping fallback — signals current platform awareness even where the honest answer is "not safe to rely on solo yet."