Morph with a shared layoutId
Share a layoutId so one component morphs into the other.
Jakub Krehel@jakubkrehelA demo component I built for my article about shared layout animations
Jakub Kreheljakub.krAll that is necessary for these elements to animate is that they share the same layoutId. Motion does all the heavy lifting to animate between them.
Jakub Kreheljakub.krWhen combiningAnimatePresenceand shared layout animations, keep components withlayoutIdoutside ofAnimatePresenceif you don’t want theinitialandexitanimations to affect them during the layout transition.
From design-motion-principles, cookbook §6 Shared Layout Animations.
Card into modal
Open a card, close it, or try Rapid.
New modal fades inBad
opacity 0→1, scale .96→1Shared layoutIdGood
layoutId={`card-${id}`}In or out of AnimatePresence
Expand, or drag Scrub to freeze mid-morph.
In AnimatePresenceBad
initial={{ opacity: 0 }} exit={{ opacity: 0 }}Out of AnimatePresenceGood
layoutId="player"Tab underline
Tap a tab, or add one with a longer name.
One underline per tabBad
opacityOne shared underlineGood
layoutId="underline"Why it matters, pros and cons
Why it matters
Seeing the card become the modal shows where it came from and where it returns.
Pros
- Origin and destination stay obvious
- Interruptible from any on-screen position
- Transform-only, stays on the compositor
Cons
- Scale distorts radius and children unless corrected
- Duplicate layoutIds morph into each other
- Skip when the origin is off screen