WebCraft

anchor-size()

A menu exactly as wide as its button

Live demo

newest
oldest
open
closed

Caveat and fallback

Caveatanchor-size() is only legal on an absolutely positioned element that has resolved an anchor, and only in sizing and inset properties; anywhere else the declaration is simply invalid. It measures the anchor's border box, so padding added to the button widens the menu with it, and a min-width alongside is worth having for the day somebody ships a two-letter label.

FallbackWithout anchor positioning the popover keeps its own width and lands at its static position, which is usually the wrong place entirely rather than merely the wrong size. Guard the whole block with @supports (anchor-name: --a) and give the unguarded version a fixed width and ordinary offsets.

Source code

HTML + CSS
<button popovertarget="menu">Sort</button>
<div popover id="menu">newest</div>

button { anchor-name: --sort; }
[popover] {
  position: absolute;
  position-anchor: --sort;
  position-area: block-end span-inline-end;
  position-try-fallbacks: flip-block;
  width: anchor-size(width);
}

Published

Questions

<details name>

How do I make a dropdown the same width as the button that opens it?

Anchor the menu to the button with anchor-name and position-anchor, then size it with width: anchor-size(width). The menu tracks the button through every reflow, which a width copied by script does only until the next one.

Why is anchor-size() not working?

It is valid only on an absolutely or fixed positioned element that has actually resolved an anchor, and only inside sizing and inset properties. A menu still in normal flow, or one whose position-anchor names an anchor-name that is out of scope, drops the declaration entirely.

What is position-try-fallbacks for?

It lists the positions to try when the first one would overflow, so flip-block lets a menu that will not fit below the button open above it instead. Without it the menu stays where you put it and is clipped at the edge of the viewport.