Stickyナビゲーションの改良版 Followナビゲーションの実装方法を解説!
一昔前まで、サイドナビゲーションをスクロールに追従させる挙動は、 position: fixed; やJavaScriptを駆使して実装していましたが、いまや position: sticky; での実装が当たり前になりました。
ただ、 position: sticky; を使った実装も完璧な挙動とはいえず、コンテンツとナビゲーションの量(高さ)によっては、たくさんスクロールしなければナビゲーションの下までなかなか到達できない場合があります。
この記事では、そんなStickyの欠点を解消する方法について紹介いたします。 改良版のUIパーツは便宜上、Followナビゲーションと呼ぶことにします。
StickyナビゲーションとFollowナビゲーションの挙動の違い
まずは、デモをご覧ください。
「sticky content」のエリアは、通常の position: sticky; による実装で
「follow content」のエリアが、Stickyナビゲーションの欠点を解消したFollowナビゲーションです。
スクロールして見ていただくとわかる通り、「sticky content」のエリアはナビゲーション最後の項目が「main content」のエリア最下部に到達するまで見ることができません。
それに比べて、「follow content」のエリアは「main content」のエリアと一緒にスクロールしていき、すぐにナビゲーション最後の項目が表示されます。そして、最下部に到達すると、画面下部にぴったりくっつきスクロールに追従してきます。
さらに、上方向にスクロールすると、今度は最上部に到達するまで「main content」のエリアと一緒にスクロールしていき、最上部に到達すると画面上部にくっつくようになります。
パッと見の動きだけをみると、なんだか単純なCSSの実装で実現できてしまいそうに思えるのですが、意外と発想の転換やコツが必要でしたので、ここからはソースコードの解説をしていきます。
実装のコツ
ベースとなる画面にくっつく挙動は position: sticky; を使う
ベースとなる「くっつく」挙動は、特に何の変哲もないですが、 position: sticky; で実現します。
「下にくっつく」挙動は top: -***px; を使う
下方向にスクロールした際の「エリア最下部が見えるところまで表示させてから下にくっつく」という挙動は bottom: 0; ではなく、 top: -***px; で指定します。
「下にくっつく = bottomを使う」という発想になりがちですが、今回はエリア最下部が見えるまでスクロールさせた後に(下にくっつくように見えるが)上でせき止めるという動きになるため、topで値を指定します。せき止める位置は、画面からはみ出しているエリア分の高さになります。
この値はJavaScriptで算出して設定します。
上方向のスクロール時にはbottomを使う、ただし下揃え必須!
下方向のスクロールとは反対に、上方向にスクロールする際には、 bottom: -***px; を指定します。
ただし、sticky指定時にbottomで追従させるには、要素が下揃えである必要があります。
また、上スクロールのときに「エリア最上部が見えるところまで表示させてから上にくっつく」という挙動をさせたいので、align-self などでの下揃えではなくmargin-topを使って値を調整しつつ追従エリアの上と親要素の上の差を設定します。(スクロール位置に合わせて可変させる)
さらに、追従エリアにmargin-topを直接指定してしまうと、「追従エリアの上と親要素の上の差」が常に同じになってしまうため、クッションとなる要素を生成し、その要素にmargin-topを指定して挟んでいます。(言葉だとちょっと何言ってるかわからないですが、そういうものだと割り切ってしまっていいものだと思います。)
まとめ
最終的なソースコードはそこまでいろんなことをしているわけではないですが、そこにたどり着くまでが大変でしたので、自分でも後で見返せるように実装方法を整理してみました。
最初からこの実装方法を知っていれば時間をかけずにコピペで再現できると思いますので、この記事を読んだかたの参考や助けになれば幸いです。