Set the transform origin

Scale from the anchor; give SVG transforms fill-box on a <g>.

From web-design-guidelines (Web Interface Guidelines), Animation.

Grow from the trigger

Open both menus, then lower the start scale.

Default originBad
transform-origin: 50% 50%
Anchored originGood
transform-origin: top right

.menu {
  position: absolute; top: calc(100% + 6px); right: 0;
  transform-origin: top right;
  transform: scale(0.95);
  opacity: 0;
  transition: transform 200ms var(--ease-out), opacity 150ms var(--ease-out);
}
.menu[data-open] { transform: none; opacity: 1; }

An SVG gear turns in place

Rotate or spin both gears, then move them.

No transform-boxBad
0,0
transform-box: view-box; transform-origin: 0 0
fill-box on a <g>Good
0,0
transform-box: fill-box; transform-origin: center

<svg viewBox="0 0 200 140">
  <g class="gear"><path d="…" /></g>
</svg>

.gear {
  transform-box: fill-box;
  transform-origin: center;
  animation: spin 4s linear infinite;
}
@keyframes spin { to { transform: rotate(1turn); } }

Type an origin

Type a transform-origin and press Enter, or pick a preset.

PopoverPlayground
Share file
…

Why it matters, pros and cons

Why it matters

Scale shows where things come from; SVG pivots on the canvas corner by default.

Pros

  • Popovers stay attached to their trigger.
  • One declaration, no JavaScript.
  • fill-box follows the shape as it moves.

Cons

  • A flipped placement needs the opposite origin.
  • Centered modals have no anchor; use center.
  • fill-box ignores stroke, so lopsided icons pivot off-center.