Shared Element Transition Between Two Views
Morph the same element from one position to another across a state change — the classic 'card-to-detail' transition powered by matching view-transition-name values.
Detailed Explanation
How Shared Element Morphs Work
If two different DOM elements share the same view-transition-name across the before-and-after snapshots, the browser interpolates the position, size, and content between them automatically. This is the killer feature of the View Transitions API.
<!-- List view -->
<a href="#detail" class="card" style="view-transition-name: hero">
<img src="thumb.jpg" />
</a>
<!-- Detail view -->
<div class="hero" style="view-transition-name: hero">
<img src="full.jpg" />
</div>
When you call document.startViewTransition(() => switchToDetailView()), the browser sees hero exists in both snapshots, captures both bounding boxes, and animates between them — including a cross-fade of the <img> content if the source URLs differ.
Generating unique names per item
For a list, you cannot reuse view-transition-name: card on every list item — names must be unique per snapshot. Generate them dynamically:
.card {
view-transition-name: var(--card-name);
}
<div class="card" style="--card-name: card-42">...</div>
Layered transitions: hero + container
You can combine a shared-element morph with surrounding cross-fades. Give the hero its name; let the rest of the page cross-fade through the root group. The browser orchestrates both in a single coordinated transition.
Performance budget
Each named element creates a snapshot group, which costs memory and a separate compositor layer. Keep named elements to fewer than 20 per transition for smooth performance on mid-range mobile.
Use Case
Pinterest-style grid → detail navigation, photo galleries opening into a lightbox, e-commerce product cards expanding into a product page, or playlist tracks animating into a now-playing view.