1. ホーム
  2. CSS

【CSS】position: sticky の使い方|追従ヘッダー・目次を作る方法と効かない原因

Share

スクロールしても画面上部に貼り付いて動かないヘッダーや、記事に追従する目次。こうした「ついてくる」表現を、JavaScript なしで実現できるのが CSS の position: sticky です。この記事では、sticky の基本的な使い方と、よくある「効かない」原因、便利な使いどころを、実際に動くデモつきで解説します。

position: sticky とは

position: sticky は、普段は通常の位置にあり、スクロールして指定した位置に達すると、そこで固定されるという性質を持つ値です。relative(通常配置)と fixed(画面に固定)の“いいとこ取り”のような動きをします。

fixed は常に画面に固定されますが、sticky はスクロール位置が条件に達するまでは普通に流れ、達したときだけ固定される点が違います。

基本の使い方

使い方はシンプルで、固定したい要素に position: sticky と、固定する位置を表す top(または bottom / left / right)を指定するだけです。

style.css
.sticky-header {
  position: sticky; /* スクロールしても追従する */
  top: 0;           /* 上端に達したら固定する */
}

top の指定は必須です。top: 0 なら画面の上端に、top: 20px なら上から 20px の位置に固定されます。この値を忘れると sticky は機能しないので注意しましょう。

動きを確認してみよう

下のデモで実際の動きを確認できます。プレビュー内を下にスクロールすると、ヘッダーが上部に貼り付いたままになります。CSS の positiontop の値を書き換えて、動きの違いも試してみてください。

<header class="sticky-header">追従するヘッダー(スクロールしてみてください)</header>
<main class="content">
  <p>セクション 1:このエリアを下にスクロールしてみてください。</p>
  <p>セクション 2:ヘッダーが上部に貼り付いたままになります。</p>
  <p>セクション 3:これが position: sticky の動きです。</p>
  <p>セクション 4:通常のスクロールと違い、ヘッダーが消えません。</p>
  <p>セクション 5:top の値で固定する位置を調整できます。</p>
  <p>セクション 6:目次やテーブルの見出しにも使えます。</p>
  <p>セクション 7:JavaScript を使わずに実装できます。</p>
  <p>セクション 8:親要素に overflow があると効かないので注意。</p>
  <p>セクション 9:もう少しスクロールしてみましょう。</p>
  <p>セクション 10:ここまで来てもヘッダーは固定されています。</p>
</main>
body {
  margin: 0;
  font-family: sans-serif;
  color: #333;
}

.sticky-header {
  position: sticky; /* スクロールしても追従する */
  top: 0;           /* 上端からの固定位置 */
  background: #4f46e5;
  color: #fff;
  padding: 16px;
  font-weight: bold;
}

.content p {
  margin: 0;
  padding: 20px 16px;
  border-bottom: 1px solid #eee;
}
Preview

sticky が効かないときに確認すること

position: sticky は「指定したのに固定されない」とつまずきやすいプロパティです。うまく動かないときは、次の3つを順に確認してみてください。

top などの固定位置を指定していない

もっとも多いのが、top(や bottom / left / right)の指定漏れです。position: sticky だけでは、どの位置で固定するかが決まらないため動きません。top: 0 のように、固定したい位置を必ずセットで指定します。

親要素に overflow が指定されている

これは見落としやすい原因です。祖先要素のどこかに overflow: hiddenautoscroll が指定されていると、その要素が新しい「スクロールの基準」になります。すると sticky はそのコンテナを基準に固定しようとし、コンテナ自体がスクロールしない場合は、固定されていないように見えてしまいます。

意図せず親に overflow が付いていないか確認しましょう。なお、はみ出しを隠す目的であれば overflow: clip を使えば sticky はそのまま動作しますcliphidden と違ってスクロールコンテナを作らないため、sticky は外側のスクロールを基準に機能し続けます。「はみ出しは隠したいけれど sticky も効かせたい」というときに便利です。

親要素の高さが足りない

sticky な要素は、親要素の範囲内でしか固定されません。親要素の高さが中身とほぼ同じだと、少しスクロールしただけで親要素ごと画面外へ出てしまい、固定が解除されたように見えます。固定を続けたい範囲の親要素に、十分な高さがあるかも確認してみてください。

こんなときに便利

  • 追従ヘッダー / ナビゲーション:スクロールしてもメニューが常に見える
  • 記事の目次:サイドに目次を sticky で固定し、読みながら移動できる
  • テーブルの見出し行:長い表でも見出しが上に残り、何の列か分かりやすい

まとめ

position: sticky を使えば、JavaScript なしで「ついてくる」要素を簡単に作れます。

  • position: stickytop をセットで指定する
  • 効かないときは「親要素の overflow」と「親要素の高さ」を確認する
  • 追従ヘッダー・目次・テーブル見出しなどに活躍する

まずはヘッダーに position: sticky; top: 0; を付けるところから試して、動きを体感してみてください。

参考リンク