View TransitionライブラリSSGOIを使ってNext.jsでネイティブアプリのような画面遷移を再現してみる
SSGOIとは
SSGOI(スゴイ)はウェブでネイティブアプリのようなページトランジションを実装することができるアニメーションライブラリです。
2025年10月現在はReact・Svelte・Vueに対応しており、Next.jsなどのフレームワークにも互換性があります。
ブラウザ標準のView Transition APIに依存しない独自の実装となっており、すべてのモダンブラウザへの対応を謳っていることも特徴の一つです。
Next.jsでネイティブアプリのような画面遷移を再現してみる
公式ドキュメントを参考に実際に触って試してみます。
今回はiOSのミュージックアプリ風の画面遷移をするモックを作ってみたいと思います。
環境
- Next.js 16.0.0
- @ssgoi/react 2.3.0
- Tailwind CSS 4.0
セットアップ
まずルートレイアウトの設定を行います。
'use client';
import { Ssgoi } from '@ssgoi/react'
import { fade } from '@ssgoi/react/view-transitions';
const config = {
defaultTransition: fade(),
};
export function SsgoiConfig({ children }: Readonly<{ children: React.ReactNode; }>) {
return (
<Ssgoi config={config}>
<div className='relative min-h-screen'>{children}</div>
</Ssgoi>
);
}
import { SsgoiConfig } from './ssgoi-config';
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode; }>) {
return (
<html lang='ja'>
<body>
<SsgoiConfig>{children}</SsgoiConfig>
</body>
</html>
);
}
初期設定はこれだけです。
横にスライドする画面遷移
進んだり戻ったりで横スライドする画面遷移を行うにはプリセットのDrill Transitionを使います。
ルーティングにはnext/linkをそのまま使えますが、それぞれのページ全体をSsgoiTransitionで囲いidを渡す必要があります。
import Link from 'next/link';
import { SsgoiTransition } from '@ssgoi/react';
import { ChevronRight, ListMusic } from 'lucide-react';
export default function Home() {
return (
<SsgoiTransition id='/'>
{/* ...(中略)... */}
<Link href={'/playlist'}>
<div className='flex items-center'>
<div className='p-2'>
<ListMusic className='size-6' />
</div>
<div className='flex-1 flex items-center border-b border-gray-200 p-2'>
<span className='flex-1'>プレイリスト</span>
<ChevronRight className='text-gray-300 size-6' />
</div>
</div>
</Link>
{/* ...(中略)... */}
</SsgoiTransition>
);
}
import Link from 'next/link';
import { SsgoiTransition } from '@ssgoi/react';
export default function Playlist() {
return (
<SsgoiTransition id='/playlist' className='bg-white'>
{/* ...(ページコンテンツ)... */}
</SsgoiTransition>
);
}
そしてルートのconfigを下記のように設定しました。
const config = {
transitions: [
{ from: '/', to: '/playlist', transition: drill({ direction: 'enter' }) },
{ from: '/playlist', to: '/', transition: drill({ direction: 'exit' }) },
],
};
これだけの設定で階層間を横スライドで遷移するアニメーションをつけることができました。

画像を拡大しながら画面遷移
次にカバー画像を拡大しながら詳細ページへ画面遷移させてみます。
今度はHero Transitionプリセットを使って実装します。
カスタムデータ属性data-hero-keyに同じidを渡すことでそれぞれのページ間で同一要素であることを指定することができます。
export default function Playlist() {
return (
<SsgoiTransition id='/playlist' className='bg-white'>
{/* ...(中略)... */}
<Link href='/playlist/1'>
<Image
src={Image1}
className='rounded-md'
data-hero-key='image-1'
/>
<div className='mt-2 text-sm'>Playlist 1</div>
</Link>
{/* ...(中略)... */}
</SsgoiTransition>
);
}
export default async function Detail({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params;
return (
<SsgoiTransition id={`/playlist/${id}`} className='bg-white'>
{/* ...(中略)... */}
<div className='w-[82%] mx-auto'>
<Image
src={Image1}
className='rounded-md'
data-hero-key={`image-${id}`}
/>
</div>
{/* ...(中略)... */}
</SsgoiTransition>
);
}
configには下記のように追記しました。
import { drill, hero } from '@ssgoi/react/view-transitions';
const config = {
transitions: [
{ from: '/', to: '/playlist', transition: drill({ direction: 'enter' }) },
{ from: '/playlist', to: '/', transition: drill({ direction: 'exit' }) },
{ from: '/playlist', to: '/playlist/1', transition: hero(), symmetric: true },
],
};
完成です。

ほんの数分でネイティブアプリのような画面遷移が実現できてしまいました。すごい。
まとめ
標準のView Transition APIと比較して、プリセットが充実していて簡単に実装できるところや、フレームワークやブラウザを問わないところがSSGOIの利点かなと感じました。
詳しくは公式ドキュメントをご参照いただければと思いますが、他にも様々なトランジションのプリセットが用意されていたり、細かいカスタマイズもできそうです。
過剰に画面遷移アニメーションをつけることは逆にUXを損ねる可能性もあることは十分注意しなければなりませんが、適切に要素の変化を伝えてくれるようなページトランジションは個人的には好きな体験です。
View Transition APIのブラウザ対応状況も進んできており、そう遠くない将来Webアプリでもアニメーションつきで画面遷移するのが当たり前の世界になるのかも?
ちょっと株式会社(chot-inc.com)のエンジニアブログです。 フロントエンドエンジニア募集中! カジュアル面接申し込みはこちらから chot-inc.com/recruit/iuj62owig
Discussion