An overlay must point at the control that opened it
Aliases: popover caret · trigger source · anchored overlay
What it is
Three identical ⋯ sit in a toolbar. The middle one is tapped; the menu drops from the top of the screen, or opens dead-centre in the content. Which of the three owns this menu is a guess. Overlay anchoring asks the layer to name its trigger with position, an arrow, or an entrance motion, so that “this layer belongs to that tap” is a visible geometric fact.
A dropdown flush with the button’s lower edge, a date picker growing out of the field, a bubble whose tail points back at an avatar — those draw the relation. A centred modal severs it by default.
Why it happens
A tap can light up several candidates at once, especially when the same glyph repeats in a row. Vision disambiguates with spatial continuity: the layer that grows from a control’s edge belongs to that control. Carets, little triangles, shared-element transitions make the continuity explicit. Without the mark the layer is an unowned panel, and the action is applied to the neighbouring lookalike.
A centred entrance adds a second illusion: it looks like a page-level dialog, so a row-level action (delete this row, share this card) is read as acting on the whole list.
Where it stops holding
A truly global decision (sign out, a system permission, an unsaved warning that spans pages) does not belong to a control; centred, pointing at nothing, is correct. A keyboard-opened menu has no on-screen source; the anchor has to become the focused control. Screen readers do not use arrows; the source relation has to live in the layer’s accessible name or labelled-by. A game HUD radial menu around the reticle is sourced from the reticle, not a button; the rule becomes “around current focus”.
Applying it
- Menus, bubbles and pickers opened by a control grow from that control’s edge by default, and point back with an arrow or a shared-element transition.
- Repeated triggers in a row (a share per card) must keep the layer on the one that was tapped. A single centred menu instance shared by the row is forbidden.
- If the trigger changes appearance on open (pressed, highlighted), keep that state until the layer closes, so the source can be checked for the layer’s whole life.
- How to check: open a layer on a UI with several identical triggers, hide the layer’s contents, leave the silhouette and the arrow, and ask “which button opened this?” A wrong point means the anchor was never built.