Next.jsでブラウザバックした際にスクロール位置を復元したい
投稿日:2022-10-04
目次
- 背景
- next.config.js の experimental.scrollRestoration を true にする
- experimental.scrollRestoration ってなんだろう?
- まとめ
背景
Next.js で実装している時に気づいたのですが、SSG しているページから別ページへ遷移してブラウザバックすると、ページの一番上にスクロールしてしまいます。
感覚としては元のスクロール位置を表示してほしいのですが、なぜか特定のページだけうまくいきません。
これではユーザー体験が良くないので、直していこうと思います。
環境
- "react": "^18.2.0"
- "next": "^12.0.10"
next.config.js の experimental.scrollRestoration を true にする
調査してみたところ、同じ現象に言及している方々を見つけました。
【Next.js】ブラウザバック時にスクロール位置を強制的に元に戻す
next.config.js の experimental.scrollRestoration を true にすることで、ブラウザバック時もスクロール位置が復帰するようになりました!
ブラウザバックした際に遷移前にスクロールしていたところに戻ってほしい · Issue #308 · zenn-dev/zenn-community · GitHub
scrollRestoration フラグ(experimental)を有効化して、スクロール位置が復元されるようになりました。
どうやらexperimental.scrollRestoration
をtrue
にすれば解決するようです。
早速以下のようにして確認してみたところ、確かにブラウザバック時にスクロール位置が復元されるようになりました。
// next.config.js
module.exports = {
experimental: {
scrollRestoration: true,
},
}
うまく動作するようになったのは良いのですが、一体experimental.scrollRestoration
って何なのでしょう?
experimental.scrollRestoration ってなんだろう?
そもそものscrollRestoration
ですが、これはHistory API
のプロパティに存在しています。
History.scrollRestoration - Web API | MDN
scrollRestoration は History インターフェイスのプロパティで、ウェブアプリケーションが履歴の移動の動作で既定のスクロール位置の復元を明示的に設定できるようにします。
値としてauto
とmanual
の 2 種類を持っており、auto
の場合はスクロール位置が保持されるようです。
Next.js の以下コードを見ると、どうやら Next.js ではauto
がデフォルトのように見えます。
next.js/router.ts at 91f0a7c60182caa1952cdb5189e99052b1aecfc9 · vercel/next.js · GitHub
それではなぜスクロール位置が復元されない場合があるのでしょうか?
この点については以下の記事がとても参考になりました。ありがとうございます。
Next.js はどうやってスクロール位置を復元するのか
Next.js はデフォルトでは experimental.scrollRestoration = false となっており、この場合の history.scrollRestoration の値は'auto'です。SPA では、history.scrollRestoration = 'auto'によるブラウザ側の復元処理がうまく動作しないことがあります。
冒頭に記載した私のケースに合致しますね。
つまり、Next.js でスクロール位置の復元を制御するのがexperimental.scrollRestoration
であり、このフラグをtrue
に設定すると、Session Storage に遷移前のスクロール位置を保存しておいて復元するようです。
処理の概要については先ほどの Zenn の記事がとても詳しいので、気になる方はそちらをご確認ください。
個人的にすごくなるほどなぁという感じだったので、あとで時間をとってコードを読み込みたいと思います。
まとめ
Next.js でブラウザバックした際にスクロール位置を復元するときは、next.config.js に以下の設定を追加すること。
// next.config.js
module.exports = {
experimental: {
scrollRestoration: true,
},
}