CSSだけでサイドバーを固定(スクロール追従)する方法

今回は、CSSだけでサイドバーを固定する方法を紹介します。

コンテンツをスクロールすると、サイドバーの一部が途中から追従する動きは、ブログなど2カラムのサイトではよく使われています。

頻繁に使われるので、実装方法を覚えてきましょう。

完成形

実際にできあがるのは以下のリンク先にあるようなサイドバーです。

サイドバーの下部にあるエリアが、スクロールに追従するようになります。

昔はJavaScriptを駆使して実装していましたが、今ではCSSだけでできるようになりました。

デモのコード

HTML

bodyやヘッダー、フッターのHTMLは省略します。

<div class="wrapper">
  <main class="main"></main>
  <aside class="sidebar">
    <div class="widget"></div>
    <div class="widget widget--sticky"></div>
  </aside>
</div>

以下のCSSで、.widget--stickyのエリアが固定されるように指定します。

CSS

デモでは分かりやすいように、各要素にグレーの色を付けてますが実際には不要なので、省略しています。

.wrapper {
  width: 94%;
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
}
.main {
  width: calc(100% - 300px);
}
.sidebar {
  width: 280px;
}
.widget + .widget {
  margin-top: 20px;
}
.widget--sticky {
  position: sticky;
  top: 20px; /* スクロール時にビューポートの20px位置に達すると固定 */
}

豊富なオリジナルブロックでLPをかんたんに作成できるLP Creator

LPをかんたんに作成できるLP Creator

デザイン・機能・SEO・収益化にこだわったメディア運営者向け「STREETIST」

デザイン・機能・速度・SEO・収益化にこだわった、ブロガー・メディア運営者向けのデザインテーマ STREETIST

解説

このCSSのポイントは2つです。

実装のポイント

  • スクロール追従させたい要素にposition: sticky
  • サイドバーの親要素はdisplay: flex
スクロール追従させたい要素にposition: stickyを入れる

追従させたい要素にposition: stickyを指定します。

topプロパティでスクロール時にどこで固定するかを指定します。

ここで固定する位置とは、指定した要素(.widget--sticky クラス)が、スクロール時に「画面の見える範囲のどこに固定するか」を決めるものです。

例えば top: 0px; にすると、その要素が「画面の一番上」に到達した時点で固定されます。

デモでは top: 20px; なので、「画面の上から 20px の位置」にその要素が達すると固定されます

.widget--sticky {
  position: sticky;
  top: 20px; /* スクロール時にビューポートの20px位置に達すると固定 */
}

それではどこまでスクロールすると、position: siticky; を指定した要素は固定解除されるのでしょうか?

それは、その要素の親要素の範囲を超えると(下端に到達すると)解除されます。

position: siticky; は、その親要素の範囲の中でのみ固定されるようになっています。

デモでは、position: stickyを指定した要素<div class="widget widget--sticky">(.widget–sticky クラス)の親要素は<div class="wrapper"> (.wrapper クラス)になっています。

この親要素<div class="wrapper">の中でのみ固定されています。

サイドバーの親要素はdisplay: flex

要素を横並びにする方法はいくつかありますが、以前ならfloatが使われていましたが、現在では主にdisplay: flexが使われます。

display: flexで横並びにすると、それぞれの要素が同じ高さになります。

floatとclearfixを使う方法だと、それぞれの要素の高さが異なります。

floatを使うと、サイドバー内にスペースがない状態になってしまいます。

これでは、スクロール追従させたい要素が動かなくなってしまうのです。

ですので、サイドバーのスクロール追従をする場合は、2カラムのレイアウトをflexboxで組んでください

今時2カラムのレイアウトでfloatを使う人はほとんどいないと思いますが、一応頭に入れておいてください。

注意点

このCSSには注意点があります。

それは、サイドバーの親要素でoverflow:hiddenを使ってはいけないという点です。

例えば、body要素やwrapperクラスにoverflow:hiddenが指定されていると、サイドバーが固定されなくなります。

/* 固定されない例 */
body {
    overflow: hidden;
}

.widget--sticky {
    position: sticky;
    top: 20px;
}

topやbottomを指定している場合、親要素にoverflow-x: hidden;なら問題なく動作します。

/* 問題なく固定される例 */
body {
    overflow-x: hidden;
}

.widget--sticky {
    position: sticky;
    top: 20px;
}

bodyで横にはみ出るのを防ぎたい場合、overflowではなくoverflow-xを使いましょう。

stickyの対応ブラウザ

position: stickyは現状、全てのモダンブラウザでサポートされています。

IEがサポート終了したので遠慮なく使って大丈夫です。

なお、今回ご紹介した position: sticky; 以外のオプションについても下記で解説しています。

よろしければご確認くださいませ。

(PR)LPをかんたんに作成できるLP Creator