thumbnail

スクロールスナップ+Vueで遷移前のページ位置に戻る方法

CSSでスクロールスナップの指定をするとスクロール量が取得できなくなります。これが原因で、Vue Routerで他のURLへ遷移して元のURLに戻る際、遷移前にいたスクロール位置に戻るコードに少し工夫が必要になります。この記事ではこの要件を満たしたコードを紹介します。

実現したい内容

Vue Routerを用いてURLを切り替えることを考えます。
元のURLをURL1、切り替え先のURLをURL2とし、URL1のページはスクロールスナップが効いているとします。
この時、実現したい内容は次のとおりです。

実現したい内容

  1. URL1でスクロールして、セクションAからセクションBへ
  2. セクションBからURL2に移動する
  3. URL2からURL1に戻ってきた時、元のセクションBの位置に直接戻る

図で説明します。

①スクロールスナップを設定しているURL1で、スクロールをしてセクションBへ移動します。
ここでセクションとは、スクロールスナップによって区切られている各要素の単位を表します。

②セクションBから、URL2のコンポーネントへ移動します。

③URL2からURL1へ戻ったとき、直接セクションBの位置へ戻ります。

問題:scrollBehaviorでは戻れない

ルーティング設定ファイルのcreateRouter()内でscrollBehavior()を呼び出せば、遷移後のページの指定位置へジャンプすることができます。しかしスクロールスナップの設定上、ここでの設定が利きません。
よって、他で元のセクションへ移動する処理を書く必要があります。

scrollBehaviorについて詳しく知りたい方は、公式のドキュメントを参照下さい。今回は使いません。

Scroll Behavior

https://router.vuejs.org/guide/advanced/scroll-behavior.html

解決:遷移後に指定した要素へ飛ぶ

要素X.scrollIntoView()を用いれば、要素Xがビューポートに入るようにスクロール(ジャンプ)してくれます。
つまり、元のセクションへ戻れます。

今回の要件を満たすコードの手順を記します。

解決策

  1. URL1の各セクションに、それぞれのセクションが一意に求まるクラスまたはIDを設定します。今回はIDとします。
  2. ページ遷移前に、直前にいたセクションBのIDを保持します。Vuexなどの外部ストアを用いても良いです。セクションのIDの検出は、Intersection Observer APIなどを用います。
  3. ページを遷移し、戻って来たときにセクションBのIDを取得します。
  4. 遷移後にdocument.querySelector(‘セクションBのID’).scrollIntoView()でジャンプします。

.scrollIntoView()によるジャンプは一瞬なので、直接元のセクションへ戻れます。

補足:スナップ時にスクロール位置が取得できない理由

この記事で紹介しています。適宜参照下さい。

ある工夫でスクロール量を取得する方法も紹介しています。

まとめ

スクロールスナップ時に、VueRouterで遷移前のセクション位置へ戻る方法を紹介しました。他にも方法はありますが、一例として説明しています。