🌊

Angular の scrollPositionRestoration の挙動確認と、最適なヘッダー/フッターレイアウトの模索

2023/02/24に公開

Web アプリで典型的な 固定ヘッダー/縦スクロール可能なコンテンツ/固定フッター という典型的なレイアウトを実装するとき、これまでは以下のようにしていました。

<header style="height: 40px;">HEADER</header>

<main>
  <div style="
    height: calc(100vh - 40px - 30px);;
    overflow-y: scroll;
  ">
    コンテンツ群
    …
  </div>

  <footer style="height: 30px;">FOOTER</footer>
</main>   

image.png

ヘッダーとフッターの高さを固定して、その間の領域を埋め、その子要素をスクロール可能とするものです。

一方で、Angular には scrollPositionRestoration という画面遷移時のスクロール位置を制御する機能があります。

scrollPositionRestoration: true の時には、ブラウザの戻る(history.back()) 時に、以前のY座標(top)を復元しようとします。これは、一覧画面→1件選択して詳細画面→一覧画面に戻ってきたとき、以前の表示位置が復元されていることが期待できる機能です。

そこで、冒頭のようなレイアウトのとき、scrollPositionRestoration: true は有効に機能するのかを確認しました。

overflow-y: scroll に scrollPositionRestoration は効かない

結果は「効かない」でした。

詳細画面から history.back() で戻ってくると、一覧画面は TOP の位置に戻ってしまいます。

Untitled3.gif

ヘッダーとフッターを Sticky にすると scrollPositionRestoration は効く

次に CSS の position: sticky で、ヘッダーを上部、フッターを下部に固定してみます。

<header style="
  height: 40px;
  position: sticky;
  top: 0px;  
">HEADER</header>

<main>
  <div>
    コンテンツ群
    …
  </div>

  <footer style="
    height: 30px;
    position: sticky;
    bottom: 0px;
  ">FOOTER</footer>
</main>   

Untitled4.gif

この場合は、scrollPositionRestoration: true は期待通りの挙動をします。
詳細画面から戻ってくると、一覧画面は元の位置を復元します。

overflow-y: scroll の時と異なるのは、ヘッダーやフッターの裏にコンテンツが存在する 事です。上のGIFのように、ヘッダーやフッターが透過だと、ヘッダーに重なって表示されます。

が、これはヘッダーフッターの背景色を非透過にする、backdrop-filter: blur(5px) でぼかす、などで解決できます。

iOS(UIKit) でも、ヘッダーやステータスバーの裏にコンテンツが重なりぼかされるような見た目のアプリはよく見るので、現在ではこちらの方がモダンと言えそうです。

且つ Angular との親和性も高いとなれば、「ヘッダーとフッターは sticky にする」 を基本とすることで問題なさそうです。

実際に動くサンプルを StackBlitz に用意しました。

こちらの「MASTER LEGACY」 が overflow-y: scroll 版、「MASTER STICKY」が position: sticky を使った版です。

参考

Discussion