はじめに
この記事では、ページ全体のランディング演出ではなく、作品一覧やポートフォリオの一部に差し込める小さなReactコンポーネントへ整理します。
複雑な分割アニメーションではなく、Reactの選択状態からメイン画像、テキスト、サムネイル、進捗バーを同期させる構造に絞ります。
今回作るもの
今回作るのは、スタジオ作品を切り替えるイメージギャラリーです。 ホバー、フォーカス、クリックのどれでも選択状態を変えられるので、マウス操作とキーボード操作の両方で同じUIを使えます。
- 主役: React stateで管理する選択中プロジェクト
- トリガー: hover / focus / click
- 対象要素: メイン画像、見出し、サムネイル、進捗バー
- 再利用先: Works一覧、ポートフォリオ、ブランド事例、記事内ギャラリー
コンポーネント設計
このデモでは、Demo が選択状態を持ちます。
activeId だけをstateにして、表示する画像やテキストは PROJECTS から派生させます。
ProjectPreview は大きな画像とメタ情報だけを担当します。
画像に key={project.id} を付けることで、選択が変わったときにCSSアニメーションを毎回走らせています。
ProjectDetails は見出しと説明文を担当します。
ここでも見出しに key を付け、画像の差し替えと同じタイミングでテキストが軽く立ち上がるようにします。
ProjectRail はサムネイルナビです。
ボタン要素にしておくと、クリックだけでなくフォーカス時にも同じ onSelect を使えるため、インタラクションの入口を増やしても状態管理は複雑になりません。
実装のポイント
一番大事なのは、アニメーションのためにstateを増やしすぎないことです。
今回必要なのは「どの作品が選ばれているか」だけなので、activeId から activeProject、activeIndex、progress を計算します。
CSS側では、画像の clip-path と scale を使って差し替え時の動きを作ります。
Reactは表示対象を切り替えるだけにして、細かな見た目の変化はCSSへ寄せています。
サムネイルには aria-pressed と data-active を持たせています。
aria-pressed は状態を支援技術へ伝えるため、data-active はCSSで選択中スタイルを当てるために分けています。
カスタマイズの考え方
作品数を増やしたい場合は、PROJECTS にオブジェクトを追加するだけです。
プレビュー、コピー、サムネイル、進捗バーは同じデータから更新されます。
動きを強くしたい場合は、imageReveal の clip-path の開始位置を大きくします。
落ち着いたギャラリーにしたい場合は、scale の差を小さくし、アニメーション時間を少し長めにすると読みやすくなります。
背景色やアクセントカラーは :root のCSS変数でまとめています。
ブランドサイトやポートフォリオへ移植するときは、まず --paper、--ink、--accent だけを調整すると全体の印象を変えやすくなります。
まとめ
このギャラリーは、React側で選択状態を明確に持ち、CSS側で画像とテキストの差し替え演出を担当する構成です。 複雑なタイムラインを使わなくても、データ、表示、状態、スタイルの責務を分けるだけで、実務に移植しやすいアニメーション部品になります。