本ブログでもCSSの3つのpositionの使い方について以前説明を行っていますが、前回のpositionの記事で触れていなかったもう一つのpositionプロパティの値stickyについて説明したいと思います。

stickyとは

stickyは、日本語では”粘着する”という意味で訳される単語です。この名前の通り、positionプロパティでstickyを設定した要素は、画面をスクロールして、その要素が画面上に現れる同時にその場所に固定することができます。1度固定したら終わりというわけではなく、今度はスクロールを元の位置に戻すと固定が解除され、本来あるべき場所に表示されます。

言葉では理解するのが難しいかもしれないので、実際にstickyが設定されているページで確認してみましょう。本ブログでは、サイドバーに配置した目次にstickyを使用しています。試しに本文書の下まで画面をスクロールしてください。右側に目次が現れてからさらにスクロールするとブラウザ上に固定される目次を確認することができるかと思います。下まで行ったら再度トップまで戻ってみてください。目次が最初に出た場所(本来あるべき場所)に戻ると固定は解除されます。

スマホで閲覧している人にはサイドバーが表示されないので動作確認を行うことはできません。また、IEなどの一部のブラウザやバージョンではstickyがサポートされていないため、上記で説明したような動作は確認できない場合があります。

stickyの設定方法

p要素に設定する場合は下記のようになります。

positionプロパティのsticky設定

positionプロパティのsticky設定


MACユーザでsafariを使用している人は、positionの設定に-webkit-stickyを設定しなければ動作しません。(2018/12/8確認済)

topプロパティに10pxと設定した場合は、固定したい要素の10px上から固定が開始されます。要素の上部に空白を作りたい場合等に活用できるかと思います。

stickyを設定したが動作しなかった例

stickyを設定すればどんな要素でも簡単に固定ができると思うかもしれませんが、stickyの設定するためにはルールを守る必要があります。

要素にstickyを設定したとしてもその親要素に高さがない場合は、動作しません。下記のように2カラムのレイアウトで、カラム全体では十分な高さはありますが、stickyを設定した要素の親要素の高さが制限されている場合は、画面をスクロールしても固定はされません。モニターの位置にスクロールしても固定されていないため、要素は表示されません。

親要素に十分な高さがない場合

親要素に十分な高さがない場合

親要素の高さが十分にある場合は、モニターの位置までスクロールするとブラウザに要素を確認することができます。

親要素に十分な高さがある場合

親要素に十分な高さがある場合

stickyは親要素の範囲内でしか動くことができないため、親要素に高さがないと固定することができません。positionではstickyに限らず、親要素との関係が重要になります。

Flexboxで作成したレイアウトでstickyを実践してみよう

実際にFlexboxで2コラムのレイアウトを作成してstickyの動作確認を行ってみましょう。

動作確認を行うために作成したレイアウトをブラウザで表示すると下記のようになります。

Flexboxを利用して2カラムレイアウト作成

Flexboxを利用して2カラムレイアウト作成

containerクラスと持つ親要素divの下にmainクラスとsidebarクラスを持つ子要素divで構成されたシンプルなものです。containerクラスにflexboxを設定します。


<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>sticky</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body> 
<div class="container">
    <div class="main">
        <h1>メイン</h1>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Autem voluptate magni excepturi, sit earum nulla quia consequatur eaque reprehenderit, molestiae dolores. Eos natus, voluptatibus nisi optio! Repudiandae ratione, perspiciatis voluptate!</p>
    </div>
    <div class="sidebar">
      <div class="list">
       <p>サイドバー</p>
       <p class="sticky_part">固定したい要素</p>
      </div>
    </div>
</div>
</body>
</html>

下記のCSSを適用しています。containerのdisplayプロパティにflexを設定し、mainとsidebarを2:1の2カラムレイアウトにしています。各領域が区別しやすいように背景色を設定しています。stickyで固定したい要素には、sticky_partクラスを設定し、positionプロパティとtopプロパティの設定を行っています。


p{
    margin: 0;
    padding: 0;
}
/* Flexコンテナ― */
.container{
    display: flex;
}
/* Flexアイテム */
.main{
    flex:2;
    background-color: #51e3d4;
}
/* Flexアイテム */
.sidebar{
    flex:1;
}
/* 固定したい要素の親要素 */
.list{
    background-color: #f3ecd3;
}
/* 固定したい要素のCSS */
.sticky_part{
    top:30px;
    position:sticky;
    background-color: #474f85;
    color:#fff;
}

親の要素に高さがない場合の動作

sticky_partクラスを設定したp要素の親要素は、listクラスを持つdiv要素になります。背景色で確認できるように親要素には背景色をつけていますが、高さが十分にないことがわかると思います。

Flexboxを利用して2カラムレイアウト作成

Flexboxを利用して2カラムレイアウト作成

この場合、画面を下記にスクロールしても固定したい要素がブラウザ上に固定されることはありません。理由は親の要素に高さがないため、下に動く領域がないためです。

親要素に高さが十分にある場合の動作

親要素に高さを持たせるためにここではheightプロパティを100%に設定します。


.list{
    background-color: #f3ecd3;
    height:100%;
}

heightプロパティを100%に設定するとlistクラスを持つdivの領域が縦一杯に広がるのが、背景色で確認できます。

親要素の要素の高さが十分にある場合

親要素の要素の高さが十分にある場合

この設定で、下に向かってスクロールを行うとブラウザに固定したい要素が固定されるが確認できます。topプロパティを30pxに設定しているので、固定したい要素の上部には30px分の領域があります。

画面をスクロールすると固定される

画面をスクロールすると固定される

まとめ

Flexboxを使用した単純な2コラムレイアウトでstickyの動作確認を行いました。ルールを知っていればCSSを数行増やすだけでsticky機能を実践することができます。サポートされているブラウザが制限されていますが、ぜひCSSの機能のみを使って簡単にsticky機能をブログに実装してみてください。