Transitions✨ Premium

View Transitions Page Reveal

The browser's real API, in a single page: document.startViewTransition() photographs the grid then the detail view, and the tapped thumbnail grows into the large visual in 0.55 s; going back returns it to its tile. A view-transition-name set just for the passage, 2.5 KB of JavaScript, instant display when the API is missing or the user reduces motion.

View TransitionsAPI native

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Transitions has 52 effects, including 9 free. Explore the category →

3 usage examples

Swatch book to fabric page — an upholsterer's website — View Transitions Page Reveal example 1

① Swatch book to fabric page — an upholsterer's website

WhenThe customer browses six swatches (corduroy velvet, washed linen, jacquard, bouclé, tweed, short-pile velvet) and taps the Prussian blue velvet to see its page.
WhyThe tapped thumbnail becomes the large visual: the customer knows it is the same fabric, and the weave stays at the same scale when large, like an unfolded remnant — without an animation library.
SettingsThumbnails drawn with repeating gradients (5 px ribs, 4 px linen weave, 36 px flower pattern); the large visual keeps the pattern size, not an enlargement; walnut-brown tones and serif title.
Home list to detail page — a social housing provider's website — View Transitions Page Reveal example 2

② Home list to detail page — a social housing provider's website

WhenAn applicant looks at the six available two-room homes and opens the one on Rue des Tanneurs: size, floor, rent and service charges, availability date.
WhyThe morph keeps the link between the list photo and the detail page; on an old browser, the page shows up immediately, losing nothing.
SettingsFacades drawn in CSS (roof, floor bands, windows) in each building's colors; light page, navy tiles and button, label band without blur; "Available 2-room homes · 6" pill.
Digital herbarium to plant page — a botanical garden's website — View Transitions Page Reveal example 3

③ Digital herbarium to plant page — a botanical garden's website

WhenThe visitor browses six fern plates and taps the bracken fern: the plate grows and becomes the page header, with the place and year it was collected.
WhyThe tapped plate grows until it becomes the page header: the visitor does not get lost between the list and the detail, and finds their plate again on return.
SettingsCream paper plates with a stem and leaflets drawn as elliptical gradients placed in percentages, which follow the visual's size; italic serif titles, undergrowth green.

How it works

The .vt-demo frame (16/11 format, 14 px corners, #0d0d18 background) holds two views: the .vt-list grid of six tiles in 3 columns, and the .vt-detail view, hidden (display: none) as long as no tile is open. Each tile is a button: a .vt-thumb thumbnail whose background carries the image or gradient, a label on a blurred 35% black band, and the detail text in the data-text attribute. All content comes from the HTML: for your products, you write your tiles, the script creates none.

On click, the script copies the thumbnail's background (color, image, size, position) and its label into the large visual .vt-hero, then sets view-transition-name: vt-hero on the thumbnail AND on the large visual. The two are never displayed at the same time: in the before state, only the thumbnail is rendered, in the after state, only the large visual. document.startViewTransition() photographs the page, runs the swap (grid hidden, detail shown, focus on "← Back"), photographs the new page, then animates: the vt-hero group goes from the thumbnail's size and place to the large visual's, while the rest of the page cross-fades. A ::view-transition-group(vt-hero) rule sets this morph to 0.55 s on cubic-bezier(.4, 0, .2, 1); the rest of the fade keeps the default duration, 0.25 s. The names are removed at the end (t.finished).

Going back does the same in reverse: the name is set again on the large visual and on the open tile's thumbnail, and the visual shrinks into its tile, which gets focus back. Measured in Chromium 151, Firefox 153 and WebKit 26.5: all six tiles open their detail, and both the way there and back start a 550 ms vt-hero group. The ::view-transition-* pseudo-elements live on the document root: a CSS variable set on .vt-demo does not reach them, hence the rule written at the root. Several grids can live on the page, each with its own state; only one view transition runs at a time in a document.

Accessibility

  • Focus: on opening, focus moves to "← Back"; on return, it goes back to the opened tile — measured in all three engines. With a keyboard: Tab to the tile, Enter to open it, then Enter again (focus is already on "← Back") to come back to the same place in the grid — measured in Chromium and Firefox, and in WebKit with Option+Tab, since Safari on Mac only stops on buttons with that key or the matching keyboard setting.
  • Reduced motion: under prefers-reduced-motion, the script does not call the API and swaps the views at once — measured in Chromium: no animation, detail shown on click.
  • Hidden view, absent view: the view not displayed is display: none, so neither read nor reachable with the keyboard. The large visual's title is plain text: in a real page, put it in an h2 so a screen reader knows the view changed.
  • Contrast: tile labels in white on a dark band, 19.3:1; detail text #a1a1aa on #0d0d18, 7.5:1. The white title on the large visual depends on the image: 5.9:1 on violet #7b2ff7, but 1.5 to 2.2:1 on the light ends (mint green, cyan, coral); add a dark gradient at the bottom of the visual or a drop shadow to the text.

Browser compatibility

Same-document View Transitions API (document.startViewTransition, view-transition-name, ::view-transition-group) and about sixty lines of JavaScript, no dependency. Measured in Chromium 151, Firefox 153 and WebKit 26.5: the API is present in all three, 550 ms morph both ways, 250 ms fade of the rest. Without the API (measured in Chromium by removing it), the views swap instantly and focus follows the same way. Public support: Chrome and Edge 111, Safari 18, Firefox 144.

Chrome 111+✓ Full
Edge 111+✓ Full
Safari 18+✓ Full
Firefox 144+✓ Full
Older browsers✓ Instant swap, no morph
Mobile iOS 18+ / Android Chrome 111+✓ Full

Without the View Transitions API or under reduced motion, the detail view replaces the grid at once, with the same content and the same focus. Without JavaScript, only the grid shows and tiles do not open: make each tile a link to a real page if the detail must stay reachable.

The code

HTML structure to paste into your page (the CSS + JS come with Premium):

index.html — structure
<div class="vt-root">
  <div class="vt-demo">
    <div class="vt-list">
      <div class="vt-grid">
        <button class="vt-tile" type="button" data-text="…">
          <span class="vt-thumb" style="background: …;"></span>
          <span class="vt-tile-label">Aurora</span>
        </button>
        … (6 tiles)
      </div>
    </div>
    <div class="vt-detail">
      <div class="vt-hero"></div>
      <div class="vt-detail-body">
        <p class="vt-detail-text"></p>
        <button class="vt-back" type="button">← Back</button>
      </div>
    </div>
  </div>
</div>
Unlock the full code — $9.90/mo incl. tax

The full HTML + CSS + JS of View Transitions Page Reveal, ready to paste — plus all 840 effects. Or $299 once, lifetime access.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Morph duration and curve (CSS — ::view-transition-group(vt-hero)) 0.55 s, cubic-bezier(.4, 0, .2, 1) 0.35 s for a snappy interface, 0.8 s for a gallery. The rule must stay at the root of the stylesheet, not under .vt-demo.
Fade of the rest of the page (CSS — ::view-transition-old(root), ::view-transition-new(root)) browser cross-fade, 0.25 s ::view-transition-old(root), ::view-transition-new(root) { animation-duration: .4s; } matches it to the morph; animation: none makes the detail appear at once around the growing visual.
Tile content (HTML — .vt-thumb, .vt-tile-label, data-text) 6 gradients, one text per tile Put a photo as the thumbnail's background-image: the large visual picks it up (size and position included). For a richer page than data-text, fill the detail view from one template per tile.
Grid (CSS — .vt-grid) 3 columns, 12 px gap repeat(auto-fill, minmax(140px, 1fr)) adapts to the width; the morph follows, since it starts from the thumbnail's real place.
Large visual height (CSS — .vt-hero height) 56% of the detail view The larger it is, the more striking the morph; keep room for the text and the back button without scrolling.
Transition name (JS — 'vt-hero') vt-hero It must be unique in the document during the passage: if another view transition on the page already uses this name, change it here and in the CSS rule.

FAQ

Shared Element moves the real element with a CSS transition on transform, between two positions written in the stylesheet: the element never changes place in the DOM, and it works everywhere. View Transitions Page Reveal lets the browser do the work: the DOM really changes (the grid disappears, the detail appears), the API photographs both states and interpolates the thumbnail into the large visual, whatever their sizes and positions. Use Shared Element for an object sliding between two known slots, Page Reveal for a list → detail passage.
The script tests typeof document.startViewTransition: without the API, it swaps directly, and the detail replaces the grid at once, with the same content and the same focus (measured by removing the API in Chromium). Nothing breaks; only the morph is missing. That is the case for Firefox before version 144 and Safari before version 18.
This effect animates inside a single document, in JavaScript. Between two pages joined by a link, the API has a JavaScript-free variant: @view-transition { navigation: auto; } in both pages' CSS and the same view-transition-name on the shared element of each page. That is the principle of Cross-Document Page Morph (fx-0800).