サイドバーを追従させる方法【CSS position:sticky】

この記事の前提条件

対象: CSS(全モダンブラウザ対応)
難易度: ★☆☆
所要時間: 約5分

ブログ記事のサイドバーにあるプロフィールや目次を、スクロールしても画面内に追従させたい…という要望、よくありますよね。以前はJavaScriptでスクロール位置を監視して座標を計算する、なんて力技が必要でしたが、今はCSSのposition: sticky;だけで実現できます。

position: stickyの基本的な書き方

追従させたい要素に、次の2つを指定するだけです。

.sidebar-profile {
  position: sticky;
  top: 20px; /* 画面上端から20pxの位置で止まる */
}

top: 20px;は「画面の一番上から20pxのところまで来たら、そこで止まって画面に固定される」という意味です。ヘッダーが固定表示(sticky/fixed)になっているサイトなら、ヘッダーの高さ分だけtopの値を大きくしておくと、要素がヘッダーの下に隠れずに済みます。

効かない時に確認すべき3つのポイント

position: sticky;は書いたはずなのに効かない、というのは非常によくあるつまずきポイントです。以下の3つを順番に確認してみてください。

topの値を指定しているか確認する

position: sticky;だけでは動きません。top(またはbottom)の値がないと、ブラウザはどこで止めればいいか判断できません。

親要素にoverflow:hiddenが付いていないか確認する

stickyにしたい要素の親(祖先)要素のいずれかにoverflow: hidden;overflow: auto;が指定されていると、sticky指定が無効になります。意外と見落としがちな原因No.1です。

親要素の高さが十分にあるか確認する

sticky要素は「親要素の範囲内」でしか追従しません。親要素の高さが、sticky要素自体の高さとほぼ同じ(=スクロールする余地がない)場合、追従しているように見えないことがあります。

⚠️ サイドバーがメインコンテンツより短い時の注意点

本文が長く、サイドバーが先に終わってしまう記事だと、追従した要素がフッターに重なって表示されてしまうことがあります。この場合は、サイドバー全体を囲む親要素の高さを本文と同じ高さまで確保しておくか、JavaScriptでフッター手前で追従を止める処理を追加する必要があります。単純なposition: sticky;だけでは対応しきれないケースがある、という点は覚えておいてください。

まとめ

  • position: sticky;topの値をセットで指定するだけで、JavaScript不要で追従表示ができる
  • 効かない時は「topの指定漏れ」「親要素のoverflow:hidden」「親要素の高さ不足」の3点を疑う
  • サイドバーが本文より短い記事では、フッターへの重なりに注意する