Appearance
LayoutMorph Plugin
LayoutMorph is a FLIP (First, Last, Invert, Play) animation plugin. It seamlessly animates elements between two completely different states in the DOM.
Click to advance tour
Welcome back
Alex Morgan
+ New Project
Monthly Revenue ↑ 12%
$24,500
Active Users ↑ 4%
1,284
Activity Overview
The three-step pattern
Animating a layout shift always follows the exact same three steps:
- Capture the current state of the elements using
LayoutMorph.record(). - Modify the DOM instantly (change classes, move elements, change flex-direction).
- Animate from the captured state using
LayoutMorph.play().
Click to trigger basic morph
Automatic edge cases
LayoutMorph automatically un-projects and preserves complex layout states without requiring manual configuration:
- Native Transforms: If an element is already rotated or skewed, LayoutMorph preserves that matrix independently of layout translations.
- Border radius & width: When elements stretch or squash, their borders usually warp. LayoutMorph automatically applies inverse-scaling so strokes don't stretch horizontally or vertically.
- Opacity: It auto-detects fade state changes and tweens opacity alongside layout geometries.
Click to morph 3D isometric card
Configuration API
Configuration objects can be passed to both record() and play() to control the behavior of the layout shift.
props - tracking CSS properties
By default, LayoutMorph tracks position and dimensions (x, y, scaleX, scaleY, rotation, skewX, and opacity). To animate standard CSS properties alongside the layout shift, declare them in the record config.
Click to toggle tracked props
stagger - cascading animations
An array of elements or a NodeList can be passed to track entire component lists. Similar to regular tweens, the standard stagger timeline property is supported in play() to orchestrate cascading reflows.
Click to trigger staggered list reflow
absolute: true - out-of-flow optimization
Normally, when elements animate across the screen, their physical bodies still take space in the layout. When rearranging a complex grid or flex container, moving bodies can displace sibling elements, causing the layout to jitter during the transition.
Setting absolute: true temporarily removes the elements from the normal page structure, allowing them to float without breaking the grid during movement. Upon animation completion, they instantly snap back into native document flow.
Click to trigger absolute wrap flow
nested: true - inverse scale correction
When a parent container scales up, all its children naturally stretch with it. Tracking a parent and a child simultaneously creates compound matrix scaling that causes the child to "double-scale".
Pass nested: true to both methods to instruct the engine to continuously invert the parent's scale matrix against the child, keeping them geometrically synced.
Click to execute nested scale inverse
Utility methods
LayoutMorph.fit(source, target)
Calculates and executes a layout bridge between two distinct DOM nodes, translating and scaling the source element to perfectly encompass the target element's bounding box.
Click to fit bounds
Timeline integration
play() returns a standard AnimX.Timeline instance. This allows subsequent procedural animations to be chained natively using standard .add() or .animate() methods immediately following layout convergence.
Click to evaluate timeline chain
Real-world composition
Combining absolute: true with tracked NodeLists allows for extremely complex native CSS property swaps (such as entirely replacing display: grid with display: flex) while maintaining 60fps tracking arrays.
Click to execute structure swap
API Reference
Importing
Via NPM (Bundlers):
js
import { LayoutMorph } from 'animx/plugins/LayoutMorph';Via CDN (Global):
js
// AnimX is exposed globally, plugins are attached automatically
const tl = AnimX.LayoutMorph.play(...)Methods
| Method | Description |
|---|---|
record(targets, props?) | Records the bounding boxes and visual styles (opacity, rotation, etc.) of target elements. Returns an opaque state object. |
play(state, config?) | Calculates difference from recorded state and instantly animates elements from old to new bounds. Returns a Timeline. |
fit(source, target, config?) | Animates the source element to perfectly encompass the exact physical bounding box of the target element. Returns a Tween. |
Configuration Options
Both play() and fit() accept an extended tween config object. Along with standard tween properties (duration, ease, delay), it supports:
| Property | Type | Default | Description |
|---|---|---|---|
absolute | boolean | false | Forces elements to position: absolute during animation. Vital for structural DOM swaps. |
nested | boolean | false | Enables scale-correction for nested morphing children. |
stagger | number | 0 | Stagger time in seconds between each element if animating a list. |
onStart | Function | null | Callback fired when the FLIP animation begins. |
onComplete | Function | null | Callback fired when the FLIP animation finishes and native layout is restored. |