2026-02-16
swup.js+Astro.js+Lenisのブラウザバックの位置ずれ
復元タイミングとスクロール制御を整理して、ブラウザバック時の位置ズレを解消したメモ。
swup.js+Astro.js+Lenisで、ブラウザバックするとスクロール位置復元がズレる問題にハマりました。
最初は高さの差が原因だと思っていたけど、実際はざっくりこちらでした。
@swup/scroll-pluginとLenisの二重更新
スクロール操作を Lenis に一本化
swup.scrollToを差し替えて、スクロール更新をLenis経由のみに統一。
swup.scrollTo = (offset, animate = true) => {
const target = Number.isFinite(offset) ? offset : 0;
savedScrollPosition = target;
lenis?.scrollTo(target, { immediate: !animate, force: true });
};
これで、
windowとLenisの二重更新がなくなる
あとはDOM高さがまだ確定していないと、targetに移動しても後から高さが伸びてズレる可能性ありそうなので、念の為復元タイミングをレイアウト確定後にする。
これでブラウザバック時の位置ズレが消えました。
scroll-pluginとLenisで挙動が違うの、冷静に見ればすぐ気づけそうなのに見事に沼りました。
こういうのあるあるですよね。
しっかりデバッグを取っていれば、もっと早く気づけたはず。
高さの取得はとってたんですけど…Lenisの存在忘れてたのが敗因です。。
そもそもLenisのような慣性スクロールは、賛否が分かれるところですよね。
自分はMagic Mouseやトラックパッドに慣れているので好みですが、個人のポートフォリオならともかく、一般的なサイトでは基本必要性ないですよね。
仮に採用する場合も、prefers-reduced-motionでは無効化するなど、逃げ道を用意しておくのがよさそうですね。
WebGL中心や演出重視であれば「体験を作る目的」で導入するのはアリかなと思いますが。。
以上、おわり。