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.

Shared Elements

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.

Try ItView Transitions API Generator

Open full tool