CSSだけでサイドメニューをスクロール追従させる方法

CSSの「position: sticky;」を使用して、表示位置を固定したスクロールに追従するサイドメニューを実装する方法の備忘録です。

実際の動きは、下記のサンプルページで確認できます。

下にスクロールすると、右側のサイドメニューが一定の高さから追従するようになります。

以前は、スクロール追従させるためにはJavaScriptの使用が必要でしたが、CSSだけで実装できるようになりました。

HTML

以下が、デモページのコードサンプルです。

<header>HEADER</header>
<div class="wrap">
  <div class="contents">CONTENTS</div>
  <div class="side-menu">SIDE MENU</div>
</div>

<body>やフッターなどのコードは、省略しています。

CSS

CSSのコードサンプルです。テキストや背景色、余白に関するコードは省略しています。

.wrap {
  display: flex;
  align-items: flex-start;
  width: 90%;
  max-width: 1200px;
  margin: 0 auto;
}
.contents {
  height: 2000px;
  margin-right: 30px;
  flex: 1;
}
.side-menu {
  flex: 0 0 30%;
  position: sticky;
  top: 30px;
}

サイドメニューを固定しているのが、.side-menuに設定した「position: sticky;」です。

コンテンツの表示位置より下に画面がスクロールされると、「top」に設定した余白を設けて追従します。

固定できない時の注意点

「position: sticky;」を設定しても、上手くスクロール追従しない時の注意点です。

設定したクラスを確認する

「position: sticky;」を設定したクラスを確認します。親クラスや違う階層のクラスに指定されていると上手く機能しません。

単純な設定ミスですが、意外と多い見落としです。

高さの差をつける

「position: sticky;」を設定した要素の高さが縦幅いっぱいだと、スクロールしてしまい追従できません。

追従させる要素と、そのままの要素の高さにある程度の差をつける必要があります。

特に上記のサンプルのように、「display: flex;」でコンテンツを横並びにした場合、そのままではフレックスアイテム同士の高さが揃ってしまうため上手く追従できません。
「align-items: flex-start;」を設定し、スクロールさせないフレックスアイテムに「height」などで高さを設定する必要があります。

フレックスアイテムに背景色がないと、見落としがちになるポイントです。

overflow: hidden;を設定している

親要素に「overflow: hidden;」が設定されていると「position: sticky;」が機能しません。

親要素だけでなく、それより上の要素(祖先要素)に設定されていても機能しないので、スクロール追従しない場合に確認するポイントです。

Share on Twitter
関連記事
Sass(Dart Sass)の使い方と便利な機能まとめ
Sass(Dart Sass)の使い方と便利な機能まとめ
CSS Flexboxの基本と使い方
CSS Flexboxの基本と使い方
スクロールで表示され固定されるメニューの作り方
スクロールで表示され固定されるメニューの作り方