Transform Origin
Set the origin point for scale, rotation, and transform animations.
Transform origin is the pivot point around which scale, rotate, skew, and other transform animations occur. By default every element transforms from its center (50% 50%), but you can move that anchor to any corner, edge, or custom position.
Basic Usage
Pass transformOrigin as a string inside from or to. It can be set on either endpoint or on both — the origin applies for the duration of the animation.
import { Motion } from "@motion.page/sdk";
// Rotate around the top-center (pendulum effect)
Motion("pendulum", ".arm", {
from: { rotate: -30, transformOrigin: "50% 0%" },
to: { rotate: 30 },
duration: 1,
ease: "power1.inOut",
repeat: { times: -1, yoyo: true },
}).onPageLoad(); Accepted Values
transformOrigin accepts the same syntax as the CSS transform-origin property.
| Format | Example | Description |
|---|---|---|
| Keywords | "center" | Center of the element (same as "50% 50%") |
| Two keywords | "top left" | Top-left corner ("0% 0%") |
| Percentages | "50% 100%" | Bottom-center |
| Pixels | "0px 0px" | Exact pixel coordinates |
| Mixed | "20px 80%" | Pixel X, percentage Y |
Keyword Reference
| Keyword | Equivalent |
|---|---|
"top left" | "0% 0%" |
"top center" | "50% 0%" |
"top right" | "100% 0%" |
"center left" | "0% 50%" |
"center" | "50% 50%" |
"center right" | "100% 50%" |
"bottom left" | "0% 100%" |
"bottom center" | "50% 100%" |
"bottom right" | "100% 100%" |
Effect on Different Transforms
Rotation
The element pivots around the origin point. Moving the origin to a corner or edge produces a hinge or pendulum effect.
// Hinge from top-left corner
Motion("hinge", ".door", {
from: { rotate: 0, transformOrigin: "0% 50%" },
to: { rotate: 90 },
duration: 0.6,
ease: "power2.inOut",
}).onClick({ each: true }); Scale
The element grows or shrinks toward the origin point. A corner origin makes the element appear to emerge from that corner rather than its center.
// Grow from the bottom-left corner
Motion("corner-pop", ".card", {
from: { scale: 0, transformOrigin: "0% 100%" },
duration: 0.5,
ease: "back.out(1.7)",
}).onPageLoad(); Skew
The shear distortion anchors at the origin, which controls which point of the element stays fixed as the rest of it tilts.
// Skew with bottom anchored
Motion("tilt", ".panel", {
from: { skewX: 15, opacity: 0, transformOrigin: "50% 100%" },
duration: 0.55,
ease: "power3.out",
}).onPageLoad(); Common Patterns
Corner Pop
Scale an element in from one of its corners — a classic way to make cards, tooltips, or dropdowns feel anchored to a fixed point.
// Dropdown opening from its top-left corner
Motion("dropdown", ".dropdown-menu", {
from: { scale: 0.8, opacity: 0, transformOrigin: "0% 0%" },
duration: 0.25,
ease: "power2.out",
}).onClick({ each: true }); Pendulum Swing
Set the origin to the top-center so the element rotates like a pendulum hanging from that point.
Motion("swing", ".pendulum", {
from: { rotate: -25, transformOrigin: "50% 0%" },
to: { rotate: 25 },
duration: 1.4,
ease: "power1.inOut",
repeat: { times: -1, yoyo: true },
}).onPageLoad(); Grow from Bottom
Reveal bar charts, progress indicators, or loaders that rise from the bottom edge.
Motion("bar-reveal", ".bar", {
from: { scaleY: 0, transformOrigin: "50% 100%" },
duration: 0.7,
ease: "power3.out",
stagger: 0.08,
}).onScroll({ scrub: false, toggleActions: "play none none none" }); Click-to-Fold Toggle
Use an edge-anchored origin with onClick to make an element fold open and shut like a flap.
Motion("flap", ".flap", {
to: { rotateX: 90, transformOrigin: "50% 0%" },
duration: 0.35,
ease: "power2.inOut",
}).onClick({ each: true, onLeave: "reverse" }); Notes
transformOriginis not animated betweenfromandto— it sets a fixed anchor for the entire animation. Place it in either endpoint; the value is applied before the tween begins.- The default is
"50% 50%"(element center). You only need to set it when you want a non-center pivot. - Pixel values are relative to the element’s top-left corner, not the page.
- For transforms applied across a multi-step timeline, set
transformOriginin the first step that needs the custom anchor.
See Scale, Skew, and Rotation for the transform properties that transformOrigin affects.