FLIP: the technique behind every smooth layout animation
Try to animate an element from one grid position to another and you hit the wall: layout properties—top, left, width, grid position—trigger reflow on every frame. Sixty reflows a second is a slideshow. Meanwhile transform animates on the compositor, silky at any complexity. The problem: transforms cannot know where the element is going.
FLIP inverts the problem: First, Last, Invert, Play. Let the layout change happen instantly, then use transforms to make it look gradual.
The four steps
// First: measure where it is
const first = el.getBoundingClientRect();
// Last: apply the change, measure again
container.appendChild(el);
const last = el.getBoundingClientRect();
// Invert: transform it back to where it was
const dx = first.left - last.left;
const dy = first.top - last.top;
// Play: release to identity — compositor does the rest
el.animate([
{ transform: `translate(${dx}px, ${dy}px)` },
{ transform: 'none' }
], { duration: 350, easing: 'cubic-bezier(.2,.8,.2,1)' });“The element already moved. The animation is a flashback.”
Why this is everywhere
Shuffle a filtered product grid, expand a card into a modal, reorder a kanban column—every buttery version of those you have seen is FLIP. Framer Motion’s layout prop, Vue’s TransitionGroup, the View Transitions API itself—all FLIP at heart: snapshot, change, invert, play.
Two practical notes. Batch your measurements—read all Firsts, mutate, read all Lasts—or interleaved reads and writes will thrash layout. And animate scale rather than width/height for size changes, correcting child distortion with inverse scales. Master the pattern once and the entire category of “impossible” layout animations becomes an afternoon task.