iTranslated by AI
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.
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:
Important Notes
As of 2026/01/10, Firefox does not support the Cross Document View Transition API, so this method will not work there.
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.
/* 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.
<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