iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
📃

Simple Implementation of Smooth Page Transitions with Cross-Document View Transitions (No JavaScript Required)

に公開

Overview

By using the View Transition API (Cross Document), you can easily implement smooth page transitions without writing any JavaScript.
https://developer.chrome.com/docs/web-platform/view-transitions/cross-document?hl=ja

Unlike methods that rely on JavaScript, this works with <a> tags and the browser's back button as well.
However, please note that when navigating via SPAs or components like Next.js's <Link>, you may still need to combine this with JavaScript-based approaches.
If you are using the <Link> component in Next.js, the following method is recommended:
https://zenn.dev/nexryai/articles/b7ce01108d6849

Important Notes

As of 2026/01/10, Firefox does not support the Cross Document View Transition API, so this method will not work there.
https://caniuse.com/cross-document-view-transitions

Even Safari supports it, so hopefully, Firefox will follow suit soon.

Implementation

Editing Global Stylesheets

Add the following code to your globally active CSS file.

While I am using SvelteKit as an example here, this approach is equally valid for other frameworks, plain HTML, PHP, and more.

src/app.css
/* View Transition API */
::view-transition-old(page-transition),
::view-transition-new(page-transition) {
  animation-duration: 0.3s;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  animation-fill-mode: both;
}

/* Entry of the new element */
::view-transition-new(page-transition) {
  animation-name: fade-interact-in;
}

/* Exit of the old element */
::view-transition-old(page-transition) {
  animation-name: fade-interact-out;
}

@keyframes fade-interact-in {
  from {
    transform: translateY(10px);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

@keyframes fade-interact-out {
  from {
    transform: translateY(0);
    opacity: 1;
  }
  to {
    transform: translateY(10px);
    opacity: 0;
  }
}

/* Enable transitions between pages */
@view-transition {
  navigation: auto;
}

Adding to the Parent Element

Assign the transition name defined in CSS (in this case, page-transition) to the common parent element you wish to animate (e.g., the main tag or a div wrapping the entire page) using the view-transition-name: property.

For SvelteKit, +layout.svelte is the ideal place, and for Next.js, layout.tsx is recommended. Other frameworks should have a similar concept where you can apply this.

src/+layout.svelte
<svelte:head>
    <link rel="icon" type="image/png" href={favicon}>
    <meta name="referrer" content="no-referrer">
</svelte:head>

<div class="main">
    {@render children?.()}
</div>

<style>
    .main {
        view-transition-name: page-transition;
    }
</style>

That is all there is to it.
It is extremely simple and allows you to support browser back buttons without writing cumbersome scripts.

Furthermore, it even works in environments where JavaScript is disabled.

Discussion