Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

View Transitions

A transition animates a change of a property: a color, a size. But when the page content is replaced entirely — new text, a different order of cards, another page — there is nothing to animate. View Transitions solve this: the browser remembers how the page looked before the change and after it, and smoothly turns one into the other.

The first transition

A transition is started from JavaScript with the document.startViewTransition() method. It is given a function that changes the page — the browser does the rest. Press the button:

<style>
  .tip { padding: 16px; background: lavender; }
</style>
 
<button onclick="nextTip()">Next tip</button>
<p class="tip" id="tip">Drink more water.</p>
 
<script>
  const tips = ["Drink more water.", "Take breaks.", "Go for a walk every day."];
  let index = 0;
 
  function nextTip() {
    document.startViewTransition(() => {
      index = (index + 1) % tips.length;
      document.querySelector("#tip").textContent = tips[index];
    });
  }
</script>

The old text fades out and the new one fades in. Without the transition it would change instantly.

Transition pseudo-elements

For the duration of the transition, the browser builds a tree of pseudo-elements above the page — snapshots of the old and new view. They are styled in CSS like regular elements:

Pseudo-elementWhat it is
::view-transitionthe layer above the page where the transition runs
::view-transition-group(name)the group of one element, moves and resizes it
::view-transition-old(name)the snapshot before the change
::view-transition-new(name)the snapshot after the change

By default the whole page is called root. Let us slow the transition down to one second:

<style>
  .tip { padding: 16px; background: lavender; }
  ::view-transition-old(root),
  ::view-transition-new(root) { animation-duration: 1s; }
</style>
 
<button onclick="document.startViewTransition(() => document.querySelector('#tip').textContent = 'Take breaks.')">Change the tip</button>
<p class="tip" id="tip">Drink more water.</p>

view-transition-name

The view-transition-name property gives an element its own name. Such an element is animated separately from the page: the browser smoothly moves it from the old place to the new one and changes its size:

<style>
  .stage { display: flex; height: 120px; padding: 8px; background: whitesmoke; }
  .ball { width: 40px; height: 40px; border-radius: 50%; background: tomato; view-transition-name: ball; }
  .stage.moved { justify-content: flex-end; align-items: flex-end; }
  .stage.moved .ball { width: 80px; height: 80px; }
</style>
 
<button onclick="document.startViewTransition(() => document.querySelector('#stage').classList.toggle('moved'))">Move</button>
<div class="stage" id="stage"><div class="ball"></div></div>

The class switches instantly, yet the ball still flies and grows — the browser built this animation.

Browser support

Transitions within a page work in all major browsers since late 2025 — Firefox added them last. For older browsers, check whether the method exists and change the page without animation:

<button onclick="update()">Update</button>
<p id="text">Before</p>
 
<script>
  function update() {
    const change = () => document.querySelector("#text").textContent = "After";
    if (!document.startViewTransition) {
      change();
      return;
    }
    document.startViewTransition(change);
  }
</script>

Transitions between pages

The same effect is possible when following a regular link to another page of the site — without JavaScript. To get it, the CSS of both pages contains the rule @view-transition { navigation: auto; }. The browser links the old and the new page, and elements with the same view-transition-name fly to their new place. This cannot be shown in the example window: it takes two real pages of one site. At the time of writing, such transitions are supported in Chrome, Edge and Safari; in other browsers the page simply opens without animation.

Common mistake

The same name on two elements. view-transition-name must be unique on the page: if a name repeats, the browser cancels the animation, and the page changes abruptly:

<style>
  .box { width: 60px; height: 40px; margin: 4px 0; background: steelblue; view-transition-name: box; }
  .wide { width: 200px; }
</style>
 
<button onclick="document.startViewTransition(() => document.querySelectorAll('.box').forEach(b => b.classList.toggle('wide')))">Change</button>
<div class="box"></div>
<div class="box"></div>

The blocks widen without animation. If there are many elements, give each one its own name: card-1, card-2 and so on.

Thanks for reading!

Donate to the site — we work hard for you.