demo · v138
Menu chevron flip
A dropdown menu where the chevron, the heading, and the colour palette of the popover automatically reflect which try-fallback the anchor engine actually picked. Scroll the viewport so each menu hits a different edge — the popover tells you exactly which fallback landed without any JavaScript layout-querying.
@container anchored(…) ships in Chrome 138 with positioning-fallback support enabled. If your browser doesn't support it, the popover renders with the default styling — the chevron and headline won't update.
The popovers are placed with position-anchor + position-area: block-end span-inline-end (below + to the right of the anchor). When that's blocked by the viewport edge, the browser walks position-try-fallbacks: flip-block (try above), then flip-inline (try to the left), then both. The container query reads which one the engine settled on.
Scroll the panel below. Each menu's popover updates its colour and chevron as it gets pushed past viewport edges.
The CSS
.menu-pop {
position: fixed;
position-anchor: --a1;
position-area: block-end span-inline-end;
position-try-fallbacks:
flip-block,
flip-inline,
flip-block flip-inline;
}
/* This is the new bit. */
@container anchored(flip-block) {
.menu-pop .where::before { content: "▲ placed above"; }
.menu-btn .chev { transform: rotate(180deg); }
}
@container anchored(flip-inline) {
.menu-pop .where::before { content: "◀ placed at start"; }
.menu-btn .chev { transform: rotate(-90deg); }
}
@container anchored(flip-block flip-inline) {
.menu-pop .where::before { content: "↖ placed at corner"; }
.menu-btn .chev { transform: rotate(135deg); }
}
Note that the container query matches an anchored element — every popover acts as its own implicit container. No container-type needed; anchored() targets the anchored element itself.
What's happening
- The popover declares an ordered list of fallbacks via
position-try-fallbacks. - The layout engine walks the list, picks the first that fits, and the popover takes that placement.
@container anchored(flip-block)matches when the engine ended up usingflip-block. Same for the others.- The popover's headline, colour, and chevron rotation all switch via CSS only — no
getBoundingClientRect(), noResizeObserver, no JS. - This was the missing primitive: previously, you knew the popover had flipped (because you watched the browser do it), but you had no way to ask why in CSS.