Zenn
👻

[Next.js] View Transitionで画面遷移にアニメーションを付ける

2025/03/24に公開

環境

以下の環境で動作確認を行った。

  • React v19.0.0
  • Next.js v15.2.3
    • use App Router
  • TypeScript v5.8.2

実装

いろいろな手法があるが、今回はなるべく簡素に実装していきたいと思う。

View Transition API

View Transition APIを利用して画面遷移時にアニメーションを付与する。まずは、アニメーションの実装をCSSで定義していく。

https://developer.chrome.com/docs/web-platform/view-transitions?hl=ja

今回は以下のAPIを利用する。

  • ::view-transition-old
  • ::view-transition-new

::view-transition-old

このセレクタは 古いビュー(遷移前のページの要素) に適用される。

基本的な構文は以下の通り。

::view-transition-old(<pt-name-selector >) {
  /* ... */
}

今回、<pt-name-selector>cross-fadeという名称にして以下のようなアニメーションを定義する。

@keyframes fadeOut {
  0% {
    opacity: 1;
  }

  to {
    opacity: 0;
  }
}

::view-transition-old(cross-fade) {
  animation: fadeOut 0.4s var(--easing-ease-in-out-circ) forwards;
}

https://developer.mozilla.org/ja/docs/Web/CSS/::view-transition-old

::view-transition-new

このセレクタは 新しいビュー(遷移後のページの要素) に適用される。

基本的な構文は以下の通り。

::view-transition-new(<pt-name-selector >) {
  /* ... */
}

::view-transition-oldと同じく、<pt-name-selector>cross-fadeという名称にして以下のようなアニメーションを定義する。

@keyframes fadeIn {
  0% {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

::view-transition-new(cross-fade) {
  opacity: 0;
  animation: fadeIn 0.6s var(--easing-ease-out) 0.2s forwards;
}

https://developer.mozilla.org/ja/docs/Web/CSS/::view-transition-new

アクセシビリティ

アクセシビリティ考慮(ユーザーの負担軽減)のため、視差効果を減らす(アニメーションの無効設定)を行うこともある。

その場合はprefers-reduced-motionと組み合わせて、視差効果を減らすが有効ではない場合にのみview-transitionが有効になるようにすると良い。

@media not (prefers-reduced-motion: reduce) {
  ::view-transition-old(cross-fade) {
    /* */
  }

  ::view-transition-new(cross-fade) {
    /* */
  }
}

https://developer.mozilla.org/ja/docs/Web/CSS/@media/prefers-reduced-motion

<ViewTransition>コンポーネントを利用する

View Transition API を React で実験的に利用できるようになった。unstable_ViewTransitionコンポーネントを利用して簡単に実装ができる。

Next.jsでViewTransitionを有効にする

Next.jsのv15.2.0以降であることが条件だが、以下の設定(experimental.viewTransition)を有効にするとViewTransitionを利用できるようになる。

// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    viewTransition: true,
  },
};

module.exports = nextConfig;

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

ViewTransitionを導入する

各要所に入れても良いが、src/app/layout.tsxに入れると一括でTransitionを付与できる(アニメーションの要件に応じて対応箇所を細かく決める必要はあるが、今回はシンプルに実装するためそうする)。

事前に用意したスタイルの名称(cross-fade)をnameに指定した<ViewTransition>コンポーネントをアニメーションさせたい要素に包括する。
unstable_ViewTransitionは分かりやすいように(コンポーネントの命名規則も踏まえて)、ViewTransitionという名称にしておく。

// src/app/layout.tsx
import { unstable_ViewTransition as ViewTransition } from "react";

export default function Layout({ children }: { children: ReactNode }) {
  return (
    <html lang="ja">
      <body>
        <Header />
        <ViewTransition name="cross-fade">
          <Main>{children}</Main>
        </ViewTransition>
        <Footer />
      </body>
    </html>
  );
}

以上の設定でNext.jsの遷移での視覚効果が有効になる。

Discussion

ログインするとコメントできます