Image Gallery Thumbnail-to-Lightbox Zoom
Zoom a thumbnail into a full-size lightbox view using a shared view-transition-name — the gold-standard photo gallery effect from native iOS and Android apps.
Detailed Explanation
The Native Gallery Pattern
Tap a thumbnail in iOS Photos: it expands to fill the screen with a smooth morphing animation. Reproduce that on the web with one CSS line per element.
<!-- Grid -->
<button onclick="openLightbox('photo-1')">
<img src="thumb.jpg" id="thumb-1" style="view-transition-name: photo-1">
</button>
<!-- Lightbox (rendered conditionally) -->
<div class="lightbox">
<img src="full.jpg" style="view-transition-name: photo-1">
</div>
function openLightbox(id) {
document.startViewTransition(() => {
showLightboxFor(id);
});
}
The browser sees view-transition-name: photo-1 exists in both the before snapshot (the thumbnail) and the after snapshot (the lightbox). It interpolates the bounding box, the aspect ratio, and the source image, producing a smooth zoom.
Aspect ratio handling
If the thumbnail is square but the full image is 16:9, the morph naturally interpolates the aspect ratio. To prevent distortion mid-animation, set object-fit: cover on the thumbnail and object-fit: contain on the full image — the browser handles the cross-fade between fits.
Loading higher-resolution images
The full-size image may not be loaded yet when the transition starts. Preload it on hover or call img.decode() before startViewTransition:
async function openLightbox(id) {
const fullImg = new Image();
fullImg.src = fullUrl(id);
await fullImg.decode(); // wait for decode to avoid pop
document.startViewTransition(() => showLightboxFor(id));
}
Closing back to the thumbnail
For close, do the reverse — same name on both elements, just hide the lightbox in the callback. The browser morphs the lightbox image back into the thumbnail's bounding box.
Use Case
Photo galleries, product image carousels with zoom, video thumbnails opening a player, and any UI where a small preview should expand into a full-size viewer with a continuity-preserving animation.