CSSのposition: sticky;を徹底解説!スクロールで要素を固定・追従させる魔法の指定

HTML/CSS

Webサイトを閲覧していると、スクロールしてもヘッダーやサイドバーの一部が画面の決まった位置に固定されたまま追従してくるのを見たことはありませんか? これはユーザーの利便性を高める上で非常に有効なデザイン手法です。

この記事では、そんな便利な動きを実現するCSSのプロパティ、position: sticky;について、その基本的な使い方から、よくある疑問、そして具体的な使用例まで、Web制作初心者の方にも分かりやすく徹底解説します。

position: sticky;とは?

position: sticky;は、CSSのpositionプロパティの一つで、要素がスクロール位置に応じて、通常の配置と固定された配置の間で切り替わる特性を持ちます。

まるで「粘着する」かのように、ある位置に達するまでは通常のコンテンツの流れの中にあり、指定した位置に達すると画面上の指定した位置に「ピタッと」固定され、スクロールに追従して表示されます。親要素の範囲を超えると、再び通常通りにスクロールされます。

よく似たプロパティにposition: fixed;がありますが、これとの違いを簡単に見てみましょう。

  • position: fixed;: 常にビューポート(ブラウザの表示領域)に固定されます。親要素や他の要素のスクロールには関係なく、常にその位置に居続けます。ヘッダーやフッター全体を固定する際によく使われます。
  • position: sticky;: 親要素の中でのみ有効です。親要素のスクロール領域内であれば固定され、親要素から外れると固定が解除されます。特定のセクションのタイトルやサイドバーの一部など、部分的に固定したい場合に非常に便利です。

position: sticky;の基本的な使い方

position: sticky;を使うには、CSSで以下の2つを指定することが必要です。

  1. position: sticky;
  2. top, bottom, left, right のいずれか、または複数

これらのオフセットプロパティ(topなど)は、「この要素がビューポートの端から何pxの位置に達したら固定を開始するか」を指定します。最もよく使われるのはtop: 0;で、これは「要素が画面上部から0pxの位置に達したら固定する」という意味になります。

基本的なコード例

以下の例では、.sample-sticky-elementが親要素.sample-areaの中で、画面上部から0pxの位置に達すると固定されます。

See the Pen
Untitled
by saku (@web-saku)
on CodePen.

HTML

<div class="sample-area"> <p>ここからスクロールすると、下の要素が固定されます。</p> <div class="sample-sticky-element"> 私はSticky要素です!スクロールすると固定されます。 </div> <div class="dummy-content"> <p>ここに長いコンテンツが入ります。</p> <p>スクロールして挙動を確認してください。</p> <p>親要素の範囲を超えると、私もスクロールします。</p> <p>...</p> <p>...</p> <p>...</p> <p>コンテンツの終わり。</p> </div> </div>

CSS

.sample-area { height: 600px; /* sticky要素の親要素に高さが必要です */ overflow-y: scroll; /* 親要素がスクロールを持つ場合 */ border: 1px dashed #ccc; padding: 10px; } .sample-sticky-element { position: sticky; top: 0; /* 画面の上部に達したら固定 */ background-color: #007bff; color: white; padding: 15px; text-align: center; font-weight: bold; } .dummy-content { height: 1000px; /* スクロールを発生させるためのダミーコンテンツ */ background-color: #f0f0f0; padding: 10px; margin-top: 20px; }

上記のサンプルで、.sample-sticky-elementが親要素.sample-areaのスクロール領域内でどのように固定されるかを確認してみてください。

なぜ動かない?stickyが機能しない時のチェックポイント

「指定したのにposition: sticky;が効かない!」という声はよく聞かれます。そんな時に確認すべきポイントをまとめました。

top, bottom, left, right の指定はありますか?

position: sticky;単体では機能しません。必ずこれらのオフセットプロパティのいずれか(通常はtopbottom)と組み合わせて指定してください。

CSS

/* OK */ .sticky-element { position: sticky; top: 0; } /* NG - これだけでは機能しません */ .sticky-element { position: sticky; }

親要素(または祖先要素)にoverflowプロパティが設定されていませんか?

親要素や祖先要素にoverflow: hidden;overflow: scroll;overflow: auto;などが設定されていると、stickyが正常に機能しない場合があります。特にコンテンツが途中で隠れるようなoverflow設定は注意が必要です。

親要素に十分な高さがありますか?

sticky要素は「親要素の範囲内で」固定されます。もし親要素の高さがsticky要素の高さと同じかそれよりも小さい場合、固定する余地がないためstickyが機能しません。sticky要素が固定されるべきスペースが親要素内に確保されているか確認しましょう。

例えば、フッターが親要素の場合、フッターの高さがsticky要素の高さより小さいと、固定されずにすぐにフッターと一緒にスクロールアウトしてしまいます。

display: inline;floattransformperspectiveは使っていませんか?

以下のようなプロパティがsticky要素自身、またはその親要素に設定されていると、stickyの挙動に影響を与えることがあります。

  • display: inline;: ブロック要素にしないと正しく機能しません。
  • float: floatが設定されている要素には適用されません。
  • transformfilterperspective: これらのプロパティが親要素に設定されていると、sticky要素がその親要素のスクロール領域として認識されなくなり、固定が解除されることがあります。

具体的な使用例

position: sticky;は、Webサイトの様々な場所でユーザー体験を向上させるために活用できます。
ここからは具体的な使用例をいくつか紹介していきます。

1. ヘッダー/ナビゲーションの追従

最も一般的な使用例の一つです。ページをスクロールしても、サイトのヘッダーやナビゲーションメニューが常に画面上部に表示されることで、ユーザーはいつでも別のページに移動したり、サイト内の主要機能にアクセスしたりできます。

See the Pen
Untitled
by saku (@web-saku)
on CodePen.

HTML

<header class="header-sticky" id="fixed-header"> <nav> <a href="#">ホーム</a> | <a href="#">製品</a> | <a href="#">お問い合わせ</a> </nav> </header> <div style="height: 1500px; background-color: #f8f9fa; padding: 20px;"> <p>ここに長いコンテンツが入ります。</p> <p>スクロールしてヘッダーが固定されるか確認してください。</p> <!-- 大量のダミーコンテンツ --> <p>...</p><p>...</p><p>...</p><p>...</p><p>...</p><p>...</p> <p>コンテンツの終わり。</p> </div>

CSS

.header-sticky { position: sticky; top: 0; /* 画面上部に固定 */ background-color: #343a40; color: white; padding: 15px 0; text-align: center; width: 100%; z-index: 1000; /* 他の要素の上に表示されるように */ } .header-sticky a { color: white; text-decoration: none; margin: 0 15px; }

ブログ記事やドキュメントサイトなどで、長いコンテンツを読んでいる途中で目次や関連情報が常に表示されるようにしたい場合に非常に役立ちます。ユーザーはスクロールすることなく、いつでも目次から別のセクションへジャンプできます。

See the Pen
Untitled
by saku (@web-saku)
on CodePen.

HTML

<div class="main-content"> <div class="article-content"> <h2>記事のタイトル</h2> <p>記事の本文がここに続きます。非常に長いです。これは<code>sticky</code>サイドバーの親要素がスクロールを持つ例です。記事の内容が長くなると、サイドバーが固定されることで、ユーザーはいつでも目次を参照できます。</p> <h3>セクション1</h3> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p> <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p> <h3>セクション2</h3> <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit.</p> <p>Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus.</p> <h3>セクション3</h3> <p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident.</p> <p>Similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus.</p> <p>記事の終わり。</p> </div> <aside class="sidebar"> <div> <input type="search" placeholder="キーワードで検索"> </div> <div id="sticky-sidebar"> <h3>目次</h3> <ul> <li><a href="#">はじめに</a></li> <li><a href="#">使い方</a></li> <li><a href="#">注意点</a></li> <li><a href="#">使用例</a></li> <li><a href="#">まとめ</a></li> </ul> </div> </aside> </div>

CSS

.main-content { height: 900px; display: flex; gap: 20px; margin-top: 20px; margin-bottom: 30px; } .article-content { flex-grow: 1; background-color: #f0f2f5; padding: 20px; border-radius: 5px; height: 900px; /* スクロールを発生させるための高さ */ overflow-y: scroll; /* コンテンツがスクロールを持つ場合 */ } .sidebar div { width: 250px; margin-bottom: 20px; background-color: #e9ecef; padding: 20px; border-radius: 5px; flex-shrink: 0; align-self: flex-start; /* flexアイテムの配置 */ } #sticky-sidebar { position: sticky; top: 20px; /* 画面上部から20pxの位置で固定 */ }

3. テーブルのヘッダー行固定

データが大量にあるテーブルで、縦にスクロールしても常にヘッダー行(<th>要素)が見えるようにしたい場合に非常に便利です。どの列が何のデータを示しているかを一目で確認できるため、データの比較や分析がしやすくなります。

See the Pen
Untitled
by saku (@web-saku)
on CodePen.

HTML

<div class="table-wrapper"> <table> <thead> <tr> <th>ID</th> <th>商品名</th> <th>価格</th> <th>在庫</th> </tr> </thead> <tbody> <!-- 20行分のダミーデータ --> <tr><td>001</td><td>ノートPC</td><td>120,000円</td><td>15</td></tr> <tr><td>002</td><td>マウス</td><td>2,500円</td><td>50</td></tr> <tr><td>003</td><td>キーボード</td><td>8,000円</td><td>30</td></tr> <!-- ...さらに多くの行... --> <tr><td>020</td><td>ウェブカメラ</td><td>6,000円</td><td>25</td></tr> </tbody> </table> </div>

CSS

.table-wrapper { max-height: 300px; /* テーブルの高さ制限とスクロール */ overflow-y: auto; border: 1px solid #dee2e6; border-radius: 5px; } table { width: 100%; border-collapse: collapse; text-align: left; } th, td { padding: 10px; border-bottom: 1px solid #dee2e6; } th { background-color: #f8f9fa; font-weight: bold; } .table-wrapper thead th { position: sticky; top: 0; /* ヘッダー行を固定 */ background-color: #f8f9fa; /* 固定時に背景が透けないように */ z-index: 1; /* データの上に表示 */ }

まとめ

position: sticky;は、CSSだけで手軽に要素をスクロールに追従させることができる非常に強力なプロパティです。以前はJavaScriptで実装する必要があった複雑なUI表現も、今ではCSSだけで実現できるようになりました。

ご紹介した「機能しない時のチェックポイント」を参考にしながら、ぜひご自身のWebサイトやポートフォリオでposition: sticky;を活用してみてください。ユーザー体験が格段に向上するはずです!

このプロパティをマスターして、よりインタラクティブで使いやすいWebサイトをデザインしましょう!

[参考]
position – CSS: カスケーディングスタイルシート | MDN > 粘着位置指定

関連記事

コメントを残す





このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください