Entry 02

Popover anchored to its trigger

Use it for dropdown menus and other popovers opened by a click. It replaces a positioning library or a script that reads getBoundingClientRect().

Open
Open the menu in each corner. It opens 8px under the button, lined up with its start edge. Near an edge it flips to stay inside the frame, and the gap stays on the button's side.
Code HTML · CSS · 2 blocks · 13 lines
<button popovertarget="menu">Options</button>
<div id="menu" popover>
  <button>Rename</button>
  <button>Delete</button>
</div>
@supports (position-area: block-end) {
  [popover] {
    margin: 0;
    margin-block-start: 0.5rem;
    position-area: block-end span-inline-end;
    position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
  }
}
Why it works, the rules and the credits 2 reasons · 4 rules · support · credits

Why it works

  1. popovertarget makes the button the popover's anchor, so no anchor names are needed.
  2. position-area places the popover on a 3×3 grid around the anchor. The fallbacks flip it when it would overflow the viewport.

Rules

  1. Use span-* values, not center. Adam Argyle found that center stops the flips when the popover is wider than its grid cell.
  2. margin-block-start is the gap between trigger and popover. The flip mirrors it, so the gap stays on the trigger's side.
  3. A popover opened by a script has no anchor and lands in the top-left corner. Pass the trigger, as in menu.showPopover({ source: button }).
  4. Write no fallback. Without support the @supports block is skipped and the popover opens centered in the viewport.

Support

Chrome
133
Firefox
147
Safari
26

Credits

Borrowed from: Una Kravets, Introducing the CSS anchor positioning API, 2024-05-10 · Saron Yitbarek, A gentle introduction to anchor positioning, 2025-08-12 · Adam Argyle, Why isn't my position-try-fallback working in small spaces?, 2024-10-12