Astro の <ClientRouter /> 導入メモ
ページ遷移時のちらつき(FOUC)が気になったので、Astro の <ClientRouter /> を導入して解決したときのメモです。
追記(2026/04/11):
FOUC の原因を取り除いたので <ClientRouter /> の使用をやめました。
参照:ページ遷移のちらつき(FOUC)は @view-transition が原因だった
Astro の <ClientRouter /> とは
Astro の <ClientRouter /> はページ遷移のアニメーションを追加したり、クライアントサイドルーティングを有効にして、SPA(シングルページアプリケーション)のような振る舞いにするコンポーネントです。
単にアニメーションが目的ならブラウザの View Transition API で十分だと思います。
導入は <ClientRouter /> コンポーネントを <head> 内に追加します。これだけで FOUC の問題が解決しました。
スクリプトの再実行
Astro のスクリプトは1回しか実行されないので、クライアントサイドルーティングでページの一部が置き換わるようになると、ページ遷移後に実行されなくなります。
ページ遷移後に実行する必要があるスクリプトに対して以下の対応を行いました。
astro:after-swap
astro:after-swap はページ遷移して新しい DOM に置き換わったとき(描画前)に発生するライフサイクルイベントです。初回表示や再読み込み時には発生しません。
テーマの設定に使用します。
<script is:inline> function applyTheme() { const theme = (() => { const localStorageTheme = localStorage?.getItem("theme") ?? ""; if (["dark", "light"].includes(localStorageTheme)) { return localStorageTheme; } if (window.matchMedia("(prefers-color-scheme: dark)").matches) { return "dark"; } return "light"; })(); document.documentElement.setAttribute("data-theme", theme); window.localStorage.setItem("theme", theme); }
document.addEventListener("astro:after-swap", applyTheme); applyTheme();</script>astro:page-load
astro:page-load はページ読み込みの最後に発生するライフサイクルイベントです。ページ遷移のたびに発生するので、特になければこれを使用します。
<script> function setupTOC() { ... }
setupTOC(); document.addEventListener("astro:page-load", setupTOC);</script>スムーススクロールを限定する
ページ全体にスムーススクロールするように設定していたので、クライアントサイドルーティングによりブラウザの戻る操作をしたときにもスクロールするアニメーションが発生するようになりました。
スムーススクロールは見出しのアンカーリンクでのみ使用したかったので、:has() と :target を使って対応します。
<html lang={site.lang} class="scroll-smooth bg-base-100 text-base-content antialiased" class="has-[:target]:scroll-smooth bg-base-100 text-base-content antialiased">まとめ
<ClientRouter />はページ遷移のアニメーションを追加したり、ページ遷移時にページの一部が置き換わるようになるコンポーネント。astro:after-swap、astro:page-loadイベントなどを使用してスクリプトをページ遷移後に実行できる。:has()と:targetでスムーススクロールの適用範囲をアンカーリンクのみに限定できる。