📃

【簡単/宣言的】Next.jsでViewTransitionコンポーネントを使って滑らかなページ遷移を実現する

に公開

概要

Next.jsではReactの実験的なViewTransition機能が使えます。
これを使うと宣言的に、かつ面倒なスクリプトを書くことなくページ間の滑らかなトランジッションが実現できます。

https://react.dev/reference/react/ViewTransition

使い方

Next.jsの設定の調整

https://nextjs.org/docs/app/api-reference/config/next-config-js/viewTransition

next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
    experimental: {
        viewTransition: true,
    },
};

export default nextConfig;

ViewTransitonコンポーネントを挟む

遷移したいページの双方のコンポーネントをViewTransitionでラップします。

src/app/page.tsx
import Link from "next/link";
import { ViewTransition } from "react";

export default async function Home() {
    return (
        <ViewTransition>
            <div className="mb-32">
                <MyContents />
                <Link href="/posts">
                    Posts
                </Link>
            </div>
        </ViewTransition>
    );
}
src/app/posts/page.tsx
import Link from "next/link";
import { ViewTransition } from "react";

export default async function Posts() {
    return (
        <ViewTransition>
            <div className="mb-32">
                <MyPosts />
                <Link href="/">
                    Back to Home
                </Link>
            </div>
        </ViewTransition>
    );
}

ここまでできたら実際に動かしてみます。

pnpm dev

通常の繊維とは違い、フェードのトランジッションがかかってることが分かると思います。

2026/01/10現在、FirefoxがCross DocumentのView Transition APIに対応していないため、aタグやブラウザの戻るボタンでの遷移をやろうとするとかなり面倒なことになります。
https://caniuse.com/cross-document-view-transitions

2024年から個人的にずっと対応してほしいと思ってたのですが、最近ようやく部分的に実装されたのみで完全な機能は使えません。

カスタマイズ

CSSでトランジッションをカスタマイズすることも可能です。ここでは例としてpage-transitionというトランジッションを用意します。

src/globals.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;
}

/* 新しい要素の入場 */
::view-transition-new(page-transition) {
  animation-name: fade-interact-in;
}

/* 古い要素の退場 */
::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;
  }
}

Reactコンポーネント側で、以下のようにViewTransitionコンポーネントにnameを渡して利用します。

    return (
        <ViewTransition name="page-transition">
    );

最後に

aタグを使ってページ遷移をする場合やブラウザの戻るボタンにも対応したい場合、MPAで同様の実装をしたい場合は Cross Document の View Transition API を使うと便利です。
https://zenn.dev/nexryai/articles/5eb519ee48bb3e

Discussion