【 更新 】おすすめ記事はこちら

【CSS】position:stickyでスクロール追従するメニューを作る

要素を指定の位置に固定するときのプロパティといえば「position : fixed」が一般的ですが、

似たようなふるまいをするもので「position : sticky」という値があります。

こちらは、ある一定の位置で「fixed」する性質で、サイドバーの一部を追従させたいときに役立つ機能

例えば、長いコンテンツの記事なら、サイドバーに目次を並べて読んでいるところが分かるようにすると、全体が把握できていいですよね。

ちなみに、本サイトの「Stork19」にも導入されています。

同じように目次を使ったサンプルで、サイドバーを固定して動きを確認してみましょう。

サンプルページ

「sticky」で固定

用意するのは、HTMLとCSSファイル。

サンプルと同じ表示にするには、reset.cssなどでデフォルトスタイルの解除が必要です。

<link rel="stylesheet" href="./css/reset.css">

また、サンプルコードでは「position: sticky」のクラスを用意して動きを適用していますが、

使いたいところに個別に指定する方法でもOK。

HTML

以下はサイドバーに表示する内容をパーツ化したものです。

.stickyクラスを用意して、動きを確認できるようにしています。

<div class="aside__block sticky"><!-- stickyクラスを適用 -->
  <div class="title-h3">
      <p>目次</p>
  </div>
  <ul class="sidebar">
    <li class="sidebar__item"><a href="#">写真管理アプリ『PHOTO』とは</a></li>
    <li class="sidebar__item"><a href="#">3つの新しい機能①</a></li>
    <li class="sidebar__item"><a href="#">3つの新しい機能②</a></li>
    <li class="sidebar__item"><a href="#">3つの新しい機能③</a></li>
  </ul>
</div>

分かりやすいように、サイドバーのパーツを3つに増やしたコードはこちら。

<aside class="aside">
  <div class="aside__block">
    <div class="title-h3">
      <p>カテゴリー</p>
    </div>
    <ul class="sidebar">
      <li class="sidebar__item"><a href="#">お知らせ</a></li>
      <li class="sidebar__item"><a href="#">サービス情報</a></li>
      <li class="sidebar__item"><a href="#">ニュースリリース</a></li>
      <li class="sidebar__item"><a href="#">ピックアップ</a></li>
    </ul>
  </div>
  <div class="aside__block">
    <div class="title-h3">
      <p>アーカイブ</p>
    </div>
    <ul class="sidebar">
      <li class="sidebar__item"><a href="#">2022年4月</a></li>
      <li class="sidebar__item"><a href="#">2021年9月</a></li>
      <li class="sidebar__item"><a href="#">2021年1月</a></li>
      <li class="sidebar__item"><a href="#">2020年4月</a></li>
    </ul>
  </div>
  <div class="aside__block sticky"><!-- stickyクラスを適用 -->
    <div class="title-h3">
        <p>目次</p>
    </div>
    <ul class="sidebar">
      <li class="sidebar__item"><a href="#">写真管理アプリ『PHOTO』とは</a></li>
      <li class="sidebar__item"><a href="#">3つの新しい機能①</a></li>
      <li class="sidebar__item"><a href="#">3つの新しい機能②</a></li>
      <li class="sidebar__item"><a href="#">3つの新しい機能③</a></li>
    </ul>
  </div>
</aside>

articleasideをメインコンテンツとしてdivで囲んだものになります。

スクロールによる追従を確認するため、CSSでコンテンツに高さをもたせるarticleを設置。

<div class="main"><!-- main -->
  <div class="main__inner">
    <article class="article">
      <div class="article__inner">
        <!-- コンテンツ -->
      </div>
    </article>
    <aside class="aside">
      <div class="aside__block">
        <div class="title-h3">
          <p>カテゴリー</p>
        </div>
        <ul class="sidebar">
          <li class="sidebar__item"><a href="#">お知らせ</a></li>
          <li class="sidebar__item"><a href="#">サービス情報</a></li>
          <li class="sidebar__item"><a href="#">ニュースリリース</a></li>
          <li class="sidebar__item"><a href="#">ピックアップ</a></li>
        </ul>
      </div>
      <div class="aside__block">
        <div class="title-h3">
          <p>アーカイブ</p>
        </div>
        <ul class="sidebar">
          <li class="sidebar__item"><a href="#">2022年4月</a></li>
          <li class="sidebar__item"><a href="#">2021年9月</a></li>
          <li class="sidebar__item"><a href="#">2021年1月</a></li>
          <li class="sidebar__item"><a href="#">2020年4月</a></li>
        </ul>
      </div>
      <div class="aside__block sticky"><!-- stickyクラスを適用 -->
        <div class="title-h3">
            <p>目次</p>
        </div>
        <ul class="sidebar">
          <li class="sidebar__item"><a href="#">写真管理アプリ『PHOTO』とは</a></li>
          <li class="sidebar__item"><a href="#">3つの新しい機能①</a></li>
          <li class="sidebar__item"><a href="#">3つの新しい機能②</a></li>
          <li class="sidebar__item"><a href="#">3つの新しい機能③</a></li>
        </ul>
      </div>
    </aside>
  </div>
</div><!-- /.main -->

メインコンテンツがあるコードから、Stickyの動きが見えるようになります。

冒頭のサンプルページに使ったコードです。breadcrumbarticleの内容は省略。

<div class="container"><!-- container -->
		
  <header class="header"><!-- header -->
    <div class="header__inner">
      <div class="logo">
        <p>LOGO</p>
      </div>
      <nav class="navigation">
        <ul class="global">
          <li class="global__item"><a href="#">トップ</a></li>
          <li class="global__item"><a href="#">お知らせ</a></li>
          <li class="global__item"><a href="#">製品情報</a></li>
          <li class="global__item"><a href="#">会社概要</a></li>
          <li class="global__item"><a href="#">お問い合わせ</a></li>
        </ul>
      </nav>
    </div>
  </header><!-- /.header -->

  <div class="headline"><!-- headline -->
    <h1 class="title-h1">お知らせ</h1>
  </div><!-- /.headline -->

  <ul class="breadcrumb"><!-- breadcrumb -->
    <!-- ぱんくずリスト -->
  </ul><!-- /.breadcrumb -->

  <div class="main"><!-- main -->
    <div class="main__inner">
      <article class="article">
        <div class="article__inner">
          <!-- コンテンツ -->
        </div>
      </article>
      <aside class="aside">
        <div class="aside__block">
          <div class="title-h3">
            <p>カテゴリー</p>
          </div>
          <ul class="sidebar">
            <li class="sidebar__item"><a href="#">お知らせ</a></li>
            <li class="sidebar__item"><a href="#">サービス情報</a></li>
            <li class="sidebar__item"><a href="#">ニュースリリース</a></li>
            <li class="sidebar__item"><a href="#">ピックアップ</a></li>
          </ul>
        </div>
        <div class="aside__block">
          <div class="title-h3">
            <p>アーカイブ</p>
          </div>
          <ul class="sidebar">
            <li class="sidebar__item"><a href="#">2022年4月</a></li>
            <li class="sidebar__item"><a href="#">2021年9月</a></li>
            <li class="sidebar__item"><a href="#">2021年1月</a></li>
            <li class="sidebar__item"><a href="#">2020年4月</a></li>
          </ul>
        </div>
        <div class="aside__block sticky"><!-- stickyクラスを適用 -->
          <div class="title-h3">
              <p>目次</p>
          </div>
          <ul class="sidebar">
            <li class="sidebar__item"><a href="#">写真管理アプリ『PHOTO』とは</a></li>
            <li class="sidebar__item"><a href="#">3つの新しい機能①</a></li>
            <li class="sidebar__item"><a href="#">3つの新しい機能②</a></li>
            <li class="sidebar__item"><a href="#">3つの新しい機能③</a></li>
          </ul>
        </div>
      </aside>
    </div>
  </div><!-- /.main -->

  <footer class="footer"><!-- footer -->
    <div class="footer__inner"></div>
  </footer><!-- /.footer -->
  
</div><!-- /.container -->

CSS

/* --- common --- */
.container {
  font-family: "游ゴシック"; /* 任意 */
  font-weight: 500; /* 任意 */
}

.sticky {
  position: -webkit-sticky; /* 任意 */
  position: sticky;
  top: 0;
}

/* --- header --- */
.header {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
}

.header__inner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px;
}

.global {
  display: flex;
  justify-content: space-around;
}

.global__item a {
  display: block;
  padding: 16px;
  color: #222;
  letter-spacing: 0.1px;
}

.headline {
  width: 100%;
  height: 160px;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 40px;
  background-color: #dcdcdc;
  color: #fff;
}

.title-h1 {
  font-size: 24px;
  line-height: 1.5;
  letter-spacing: 0.1rem;
}

/* --- main --- */
.main {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
}

.main__inner {
  display: flex;
}

.article {
  width: calc(100% - 360px);
  min-height: 2000px; /* スクロール用に高さ指定 */
}

.aside {
  width: 320px;
  margin-left: 40px;
}

.aside__block {
  margin-bottom: 40px;
}

.title-h3 {
  padding: 16px 0;
  border-top: solid 2px #dcdcdc;
  margin-bottom: 8px;
}

.title-h3 p {
  font-size: 18px;
  letter-spacing: 0.1px;
}

.sidebar__item {
  border-bottom: solid 1px #dcdcdc;
}

.sidebar__item a {
  display: block;
  padding: 16px 0;
  color: #222;
  letter-spacing: 0.1px;
}

/* --- footer --- */
.footer {
  padding: 40px;
  background-color: #222;
}

「stickyfill」で対応(IE)

Internet Explorerは「position: sticky」に対応していません。

代わりに「stickyfillというライブラリを読み込むことで利用できるようになります。

GitHubから圧縮ファイルをダウンロードし、distフォルダにある「stickyfill.min.js」を使用。

ただ、2022年6月15日(日本時間は16日)にIEのサポートが終了するので、対応としては少ないかもしれません。

必要に応じて取り入れてください。

JavaScript

先に</body>の直前にスクリプトを読み込みます。

<script src="stickyfill.min.js"></script>

本記事のサンプルで使っている.stickyクラスを指定。

<script>
    var elements = document.querySelectorAll('.sticky'); Stickyfill.add(elements);
</script> 

他のクラス名にした場合は、カッコ内のクラス名を変更してください。

jQuery

こちらも先に</body>の直前にスクリプトを読み込みます。

<script src="stickyfill.min.js"></script>

jQueryを使うときは、別途、jQueryのライブラリを忘れずに読み込んでください。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

本記事のサンプルで使っている.stickyクラスを指定。

<script>
    var elements = $('.sticky'); Stickyfill.add(elements);
</script>

他のクラス名にした場合は、カッコ内のクラス名を変更してください。

おわりに

スクロール位置を取得するような操作もなく、導入できるのが「position: sticky」のいいところ。

利用頻度としては少ないものの、「stickyfill」ライブラリがあるおかげで、意外にもブラウザ問わず利用できます。

ちなみに、Edgeならライブラリなしで動作するので、IEへの対応は要件に応じて取り入れてください。

サイドバーでの活躍が多いプロパティですが、パララックス効果を手軽に実装したいときにも、ぜひ試してみてくださいね。