Two screens, or one screen changing
When a user taps a thumbnail in a grid and lands on a detail page, there are two stories the interface can tell.
The first: this grid is gone, and here is a different page. The second: this item you tapped is the thing now filling your screen. The second story is nearly always the true one, and a transition is how you tell it.
The technique has a name in every framework (shared element transition, hero animation, container transform, view transition) and the same mechanism underneath. You identify one element that exists in both states, measure where it is in each, and animate between the two measurements while the rest of the interface cross-fades.
FLIP: the mechanism, in four steps
The standard implementation is called FLIP, from Paul Lewis, and it is worth understanding even if a framework does it for you, because when a shared-element transition goes wrong the fault is always in one of these four steps.
- First. Before anything changes, measure the element’s position and size. In the browser this is
getBoundingClientRect(). - Last. Apply the final state (swap the DOM, navigate, change the layout) and measure again, immediately, before the browser paints.
- Invert. Compute the difference and apply a
transformthat puts the element visually back where it started. The element is now in its final position in the layout, but looks as though it never moved. - Play. Remove the transform with a transition. The element travels from the inverted position to its real one.
The reason for this dance rather than animating width, height, top and left: steps 3 and 4 use only transform, which the browser can animate on the compositor without re-running layout. Animating the geometry properties directly means a full layout calculation on every frame, which is where dropped frames come from.
What makes one look wrong
Three failures cover nearly all of them.
The aspect ratio changes during the move. A 1:1 thumbnail becoming a 16:9 header will squash visibly if you animate width and height independently. The fix is to animate a uniform scale and crop, or to cross-fade between two correctly-cropped images at the midpoint where the distortion is least visible. Most frameworks that do this well are cross-fading and hoping you do not look.
The text comes along for the ride. Scaling a container scales the type inside it, so a 14px caption becomes a blurry 32px caption mid-flight and then snaps back. The standard fix is a counter-scale: scale the child by the inverse of the parent’s scale each frame, so the text stays at its true size throughout.
Nothing corresponds. If the two screens share no element, a shared-element transition has to invent one, and the result is a shape morphing into an unrelated shape. This reads as a special effect rather than an explanation. A cross-fade is the honest answer.
The rule underneath
The transition should describe a relationship that is already true in your data model.
- Tapping an item in a list and seeing that item expand: the item is the same object. Shared element is correct.
- Moving from step 2 to step 3 of a form: these are positions in a sequence. A horizontal slide is correct, and the direction should reverse when going back.
- Switching between two unrelated top-level tabs: there is no journey. A cross-fade, or nothing, is correct. Sliding implies the tabs sit side by side in a space, which is a claim you probably do not want to make, and which breaks the moment somebody navigates to the fourth tab from the first.
When a transition is hard to design, it is usually because you are trying to describe a relationship that does not exist.
Doing it without a framework
The browser now has document.startViewTransition(), which handles the capture-and-interpolate work natively for same-document changes and, with the multi-page variant, across navigations. You tag the element in both states with the same view-transition-name and the browser does the FLIP for you. It degrades to an instant change in browsers that do not support it, which is the correct fallback.
For everything else, FLIP in about thirty lines of plain JavaScript covers it, no library required. GSAP’s Flip plugin and Motion’s layout animations are convenience on top of the same four steps.
The free path
- View Transitions API: built into the browser, nothing to install.
- Motion (the open-source successor to Framer Motion): free, and its
layoutprop is FLIP with the measurement handled. - GSAP: now free for all use including commercial, Flip plugin included.
- Penpot: open-source design tool, enough prototyping to test a transition before building it.
The limitation
A shared-element transition costs frames, and it costs them at the worst moment: while a new screen is mounting and probably fetching data. On a low-end device, the transition and the render compete, and the result is a janky animation followed by a late-arriving screen: worse than no transition at all.
The defensible rule is to make the transition cancellable and to skip it under load. If the element’s destination is not measurable within one frame, do not animate; just change. A transition is an explanation, and an explanation delivered badly is worse than none.
Every lesson here is open. Your progress is recorded once you pass the Video with AI exam.
Check your understanding
In a FLIP transition, why is the element moved back to its starting position with a transform in step three rather than by animating its top and left values directly?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Deepa, your AI tutor