position: sticky;はIE非対応のプロパティのため、以前まではポリフィルを利用するか、fixedで代用するか、のどちらかで対応していました。
ですが、現在はIEのサポート終了によって利用する機会が多くなりました。
今回は、そんなposition: sticky;の便利な使い方と注意点を、デモとサンプルコード付きでご紹介していきます。
fixedと似た動きをしますが、stickyの方が簡単で便利だと思いますので、あまり利用していないという方はぜひこの機会にstickyも使ってみてください!
目次
position: sticky;とは
position: sticky;は、粘着位置指定といい、親要素を基準に配置され、スクロールに応じて親要素の範囲内で基準に追従させるプロパティです。
追従する点で、position: fixed;に似ています。
また、top、left、right、bottomを使用して相対位置の指定ができます。
参考ドキュメント:position「粘着位置指定」
position: fixed;との違い
動きはfixedとよく似ているstickyですが、大きく違う点が2つあります。
fixedはウィンドウを基準に配置されますが、stickyは親要素を基準に配置されます。
そのため、親要素の一番下までスクロールすると自動的に要素が親要素の下部で止まります。
fixedでは任意の場所で止めたい場合はjsでpositionの値を切り替えるなどの処理が必要でしたが、stickyでは必要ありません。
また、fixedでは要素のwidthやheightはなくなり、要素が浮きますが、stickyは保たれたままになります。
利用する際の注意点
stickyを利用する際は、いくつかの注意点があります。
stickyがうまく動かない……、という場合は、以下に当てはまらないか確認してみてください。
親要素にoverflowが指定されている
親要素に、overflow: visible;以外の値(auto, hidden, scroll)が指定されていると、追従してくれません。
直上の親だけでなく、さらに上の祖先要素でも同様なので、うまく動かない場合はどこかにoverflowが指定されていないか確認してみてください。
topを指定していない
stickyの要素にtopが指定されていない場合は追従しません。
一番外側(要素のフチ)で追従の場合は、top: 0;でよいです。
親要素に高さがない
親要素の中にsticky要素しかない場合は、スクロールするだけのエリアがないため追従しません。
stickyは親要素を基準に追従するため、親要素の高さを、sticky要素を追従させたい高さに設定する必要があります。
便利な使い方4選
stickyを使うと、これまでjsでの実装や細かな調整が必要だったパーツをより簡単に作成することができます。
次から実践的な使い方を、デモ・サンプルコード付きでご紹介いたします。
サンプルコードには、重要な箇所に // ★ とコメントを入れていきます。
全てのデモが一度に見れるデモサイトも用意しましたので、こちらもぜひご覧ください。
デモサイト
パララックス
みなさん、パララックスを実装するときはどのように実装していますか?
パララックスのパーツが複数あって細かな調整をしたい場合は、プラグインの導入を検討したいですが、背景画像が1枚パララックスするのみなら、CSSで簡単に実装したいですよね。
background-attachment: fixed;というパララックスを実装するのに便利なプロパティがありますが、こちらはbackground-size: cover;と組み合わせて使ったときに、iOSで不具合が起こってしまいます。
※不具合が起こるのはiOSのみでその他のモダンブラウザでは問題なく動作しますので、スマホ対応が不要なら、background-attachment: fixed;で実装するのもよいと思います。
stickyで実装する場合
スマホ対応をしたい場合が多いため、パララックス背景はposition: fixed;を利用して実装することが多かったのですが、
fixedでウィンドウの背景に常に表示されるのでパララックス背景が不要なエリアにはbackground-colorを指定しておいたり、背景画像の方が要素より上に表示されるため、ページ内の要素にposition: relative; z-index: 1; を付けておくなどの調整が必要で、若干手間がかかります。
また、fixedはウィンドウ基準で背景を設定するため、同一ページに複数実装したい場合はjsでスクロール位置を取得して画像を切り替える、といった調整が必要になります。
対して、stickyは親要素を基準とするため、1ページにいくつも背景画像を設定できます。
また、stickyで実装する場合も、背景画像が中身のコンテンツよりも上に表示されるためz-index: -1;、親要素はz-index: 1;としておきます。
※fixedと違い、パララックス背景のエリアに適用させるのみで大丈夫です。
背景画像を表示させたい要素(.inn)の中に、画像用の子要素(.parallax-bg)を設置します。
.parallax-bgの範囲を.innの大きさに広げて、.innの中をstickyで追従するように設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | // HTML <div class="parallax-sticky"> <div class="bg-cont"> パララックス背景無しの要素 </div> <div class="inn"> パララックス背景有りの要素 <div class="parallax-bg"><div class="bg bg01"></div></div> </div> <div class="bg-cont"> パララックス背景無しの要素 </div> <div class="inn"> パララックス背景有りの要素 <div class="parallax-bg"><div class="bg bg02"></div></div> </div> <div class="bg-cont"> パララックス背景無しの要素 </div> </div> // CSS .parallax-sticky .inn { position: relative; // ★ z-index: 1; // ★ } .parallax-sticky .parallax-bg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; } .parallax-sticky .parallax-bg .bg { background: no-repeat center center/cover; width: 100%; height: 100vh; position: sticky; // ★ top: 0; // ★ z-index: -1; // ★ } .parallax-sticky .parallax-bg .bg01 { background-image: url("../img/bg01.jpg"); } .parallax-sticky .parallax-bg .bg02 { background-image: url("../img/bg02.jpg"); } |
(おまけ)fixedで実装する場合
下記がfixedで実装する場合のデモとサンプルコードになります。
背景画像を表示させたい要素に、疑似要素で画像を設定します。
背景画像が中身のコンテンツよりも上に表示されるため、z-index: -1;、親要素はz-index: 1;としておきます。
※この対応は、パララックス背景のエリアのみでなく、ページ全体に行う必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | // HTML <div class="parallax-fixed"> <div class="bg-cont"> パララックス背景無しの要素 </div> <div class="inn"> パララックス背景有りの要素 </div> <div class="bg-cont"> パララックス背景無しの要素 </div> </div> // CSS .parallax-fixed { position: relative; // ★ z-index: 1; // ★ } .parallax-fixed::before { background: url("../img/bg01.jpg") no-repeat center center / cover; content: ""; display: block; width: 100%; height: 100%; position: fixed; // ★ bottom: 0; top: 0; right: 0; left: 0; margin: auto; z-index: -1; // ★ } |
一点、注意点として、stickyは範囲内でスクロールが始まってから画像が追従します。
fixedはスクロール位置が範囲外でも画像がウィンドウ基準に追従されるため、fixedの方が動きが合ってよりリッチなパララックス背景に見えます。
イメージと違う場合は、fixedの実装やjsプラグインの利用を検討してみてください。
追従ヘッダー
追従ヘッダーはこれまでfixedで実装してきましたが、fixedでは要素の高さがなくなるため、ヘッダーの次の要素がヘッダーに埋もれてしまうため、margin-topやpadding-topでヘッダーの高さ分の余白を取っておく必要がありました。
stickyなら要素の高さはそのままなので気にする必要がありません。
ヘッダー全体が追従
追従させたい要素を全てheaderタグで囲み、headerタグにstickyを付けて追従させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | // HTML <div class="header-wrap"> <header> <div class="logo">Logo</div> <nav> <ul> <li>メニュー01</li> <li>メニュー02</li> <li>メニュー03</li> </ul> </nav> </header> <div class="cont"> 要素 </div> </div> // CSS .header-wrap header { background: #fff; box-shadow: 0px 0px 16px -6px rgba(0,0,0,0.6); width: 100%; display: flex; position: sticky; // ★ top: 0; // ★ } .header-wrap header .logo { color: #083cac; font-size: 18px; font-weight: bold; padding: 15px; } .header-wrap nav ul { display: flex; justify-content: center; height: 100%; } .header-wrap nav ul li { display: flex; align-items: center; justify-content: center; padding: 15px; text-align: center; height: 100%; } |
ナビだけ追従
ヘッダーの一部分(グローバルナビ)だけを追従させたい場合は、ロゴのエリアとナビをひとまとめに囲むのではなく、追従させたいエリアのみ外(追従させたい範囲の直下)に出しておきます。
ロゴのエリアをスクロールで通り過ぎたときに、ナビのみ、画面上部に追従していきます。
fixedで実装する場合は、jsでスクロール量を取得して、ヘッダーのpositionをabsoluteからfixedに付け替える、などの処理が必要ですが、stickyではたった2行で実装することができます!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | // HTML <div class="header-nav-wrap"> <header> <div class="logo">Logo</div> </header> <nav> <ul> <li>メニュー01</li> <li>メニュー02</li> <li>メニュー03</li> </ul> </nav> <div class="cont"> 要素 </div> </div> // CSS .header-nav-wrap header { width: 100%; } .header-nav-wrap header .logo { color: #083cac; font-size: 18px; font-weight: bold; padding: 15px; } .header-nav-wrap nav { background: #083cac; position: sticky; // ★ top: 0; // ★ } .header-nav-wrap nav ul { display: flex; justify-content: center; height: 100%; } .header-nav-wrap nav ul li { background: #083cac; color: #fff; display: flex; align-items: center; justify-content: center; padding: 15px 30px; text-align: center; height: 100%; } .header-nav-wrap nav ul li + li { border-left: 1px solid #fff; } |
追従サイドバー
スクロールに合わせて追従するサイドバーが簡単に実装できます。
注意点として、flexで横並びにすると左右の要素の高さが揃います。
このままだとうまくstickyで追従しませんので、align-items: flex-start;で上揃えにしてサイドバーの高さを要素の高さまで縮めてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | // HTML <div class="sidebar-wrap"> <div class="cont"> <p>要素</p> </div> <div class="sidebar"> <p>サイドバー</p> <ul> <li>メニュー01</li> <li>メニュー02</li> <li>メニュー03</li> </ul> </div> </div> // CSS .sidebar-wrap { display: flex; align-items: flex-start; // ★flexで横並びにする場合は、要素の高さが揃ってしまうためflex-startに flex-direction: row-reverse; } .sidebar-wrap .cont { padding-left: 30px; width: 60%; min-height: 800px; } .sidebar-wrap .sidebar { position: sticky; // ★ top: 0; // ★ width: 40%; } .sidebar-wrap .sidebar p { font-weight: bold; margin-bottom: 10px; } .sidebar-wrap .sidebar ul li { background: #c0dbf3; padding: 15px; } .sidebar-wrap .sidebar ul li + li { border-top: 1px solid #fff; } |
追従見出し
解説ページなどで見出しの項目が多い場合などに便利な、追従する見出しです。見出しが追従すると、いま何の項目について読んでいるのかがわかりやすいですね。
fixedで実装しようと思うと結構大変かもしれませんが、stickyなら簡単に作成できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | // HTML(ダミーテキストは省略) <div class="head-sticky-wrap"> <div class="inn"> <h2 class="ttl">追従タイトル01</h2> <p>01エリア<br> テキストテキストテキストテキストテキストテキスト…</p> </div> <div class="inn"> <h2 class="ttl">追従タイトル02</h2> <p>02エリア<br> テキストテキストテキストテキストテキストテキスト…</p> </div> <div class="inn"> <h2 class="ttl">追従タイトル03</h2> <p>03エリア<br> テキストテキストテキストテキストテキストテキスト…</p> </div> <div class="inn"> <h2 class="ttl">追従タイトル04</h2> <p>04エリア<br> テキストテキストテキストテキストテキストテキスト…</p> </div> </div> // CSS .head-sticky-wrap .inn { padding: 20px; } .head-sticky-wrap .ttl { background: #e3ebec; color: #083cac; font-weight: bold; margin-bottom: 20px; padding: 10px; position: sticky; // ★ top: 0; // ★ } |
まとめ
今回は、stickyの便利な使い方を紹介いたしました。
fixedよりも簡単に実装できる場合が多く、重宝するのではないでしょうか? まだあまり使っていないという方は、ぜひ使ってみてください!
個人的には、同じページにいくつもパララックス背景を設置するのが面倒だったので、stickyで簡単に設置できるようになって助かっています。
本記事がみなさんのコーディングのお役に立てますと幸いです。