View Transitions によるリスト並び替えアニメーション

データのソート・フィルタ・シャッフル時にリストアイテムを新しい位置へなめらかにアニメーション。React Spring/Framer Motion の FLIP レイヤーを完全に置き換える。

Shared Elements

詳細な説明

FLIP を無料で

View Transitions API 以前、リスト並び替えのアニメーションには FLIP(First, Last, Invert, Play)が必要でした。古い位置を測定 → DOM を変更 → 新しい位置を測定 → 逆変換を適用 → identity へアニメーション。Framer Motion の <AnimatePresence layout> などのライブラリがこれを自動化していましたが、メガバイト単位の JavaScript を抱える羽目になります。

View Transitions では、各アイテムに固有の名前を付けるだけで十分です:

.todo-item {
  view-transition-name: var(--item-name);
}
{todos.map(t => (
  <li key={t.id} style={{'--item-name': `todo-${t.id}`}}>{t.text}</li>
))}
function sortTodos() {
  document.startViewTransition(() => {
    setTodos([...todos].sort((a, b) => a.priority - b.priority));
  });
}

ブラウザはソート前に named 要素の位置を全てキャプチャし、React のコミット後に再キャプチャ、各要素を行き先までアニメーションします。

入退場アニメーションの追加

追加 または 削除 されるアイテムには、ブラウザがデフォルトのクロスフェードにフォールバックします。上書きするには:

::view-transition-new(.todo-item) {
  animation: 250ms ease-out both fade-in-up;
}

ネストしたトランジション

リストがトランジションするルート内にある場合、外側のルートトランジションが内側のアイテムトランジションを内包します。このネストは自動的に処理され、手動の協調は不要です。

エッジケース:長いリスト

100以上のアイテムを持つリストでは全部に名前を付けると 100以上のスナップショットグループが生成されます。IntersectionObserver で可視性をトグルし、ビューポート内のアイテムだけview-transition-name を付けることを検討してください。

ユースケース

ソート可能なリストを持つ Todo アプリ、カードを並び替えるカンバンボード、順位を更新するリーダーボード、再ソートする検索結果、ユーザー入力に応じて行順序が変わるデータテーブル全般。

試してみるView Transitions API ジェネレーター

フルツールを開く