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;
}

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

解説

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

実装のポイント

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

追従させたい要素にposition: stickyを指定します。topプロパティでどの位置で固定するかを指定します。

要素を横並びにする方法はいくつかありますが、以前なら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がサポート終了したので遠慮なく使って大丈夫です。