Squash Stretch
The animation principle, as a primitive. Install with npx remotion-ui@latest add squash-stretch.
PrimitivePrimitives
$ npx remotion-ui@latest add squash-stretchWeight, without a physics engine.
import { SquashStretch } from "@/remotion/primitives/squash-stretch";
<SquashStretch mode="bounce" periodInFrames={36}>
<Ball />
</SquashStretch>Three shapes of one idea
bounce is the textbook ball: it flattens on contact, elongates through the
fast part of the travel, and hangs round at the apex where it is slowest.
pulse is the same deform without the travel, for a logo or an icon that needs
weight in place.
impact fires once, for something landing into a layout — pair it with an
entrance primitive, which owns the arrival, and let this own the landing.
Volume preservation
scaleX is the reciprocal square root of scaleY, which keeps
scaleX² × scaleY constant — the volume of a body of revolution, and the same
rule an animator draws by. Squashing one axis without widening the other is the
single thing that makes a deform read as a scale bug rather than as rubber,
because the eye tracks area.
Pivot
origin defaults to bottom, the floor contact. A deform around the centre
lifts the element off its own baseline and the floor stops reading as a floor.
Use center only when the element is genuinely free-floating.
Timing
contact is how much of the cycle the flatten lasts. Short contacts read as
hard surfaces; long ones read as soft ones. The squash is the frame everyone
remembers, so if you are picking a poster frame or a loop point, pick a contact.
Volume is preserved: `scaleX` is the reciprocal square root of `scaleY`, because the eye tracks area and a one-axis squash reads as a scale bug. The pivot is the bottom by default — deforming around the centre lifts the element off its own baseline and the floor stops reading as a floor.
Agent notes
Install first, then import the copied source component locally. AI guide →
@/remotion/primitives/squash-stretch- Use when: frame-level motion primitives and reusable animation wrappers.
- Customize: mode, periodInFrames, travel, squash, plus copied source for timing, layout, colors, and typography.
- Rule: do not import this component from the
remotion-uinpm package; it is copied into your project.
Usage
import { SquashStretch } from "@/remotion/primitives/squash-stretch";
<SquashStretch mode="bounce" periodInFrames={36}>
<Ball />
</SquashStretch>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | - | What deforms. |
| mode | "bounce" | "pulse" | "impact" | "bounce" | Travel and deform, breathe in place, or deform once. |
| periodInFrames | number | 36 | Length of one cycle. |
| travel | number | 90 | Bounce height, in px. 0 deforms in place. |
| squash | number | 0.28 | How hard it flattens on contact. Above 0.4 reads as cartoon. |
| stretch | number | 0.16 | How far it elongates at speed. |
| startAtInFrames | number | 0 | Frame the cycle starts on. |
| contact | number | 0.22 | How much of the cycle the contact lasts, 0-1. |
| origin | "bottom" | "center" | "top" | "bottom" | Pivot. `bottom` is the floor contact. |