プログラミング

グローバルメニューをスクロールに合わせて追従させる方法【コピペOK】

投稿日:

よく色んなサイトで見る、スクロールに合わせてグローバルメニューが移動する機能を実装したい。と思っている人にその方法について解説していきたいと思います。

とは言っても簡単で、CSSと少しのJavaScriptだけで実装できます。
早速解説していきましょう。

グローバルメニューが画面の一番上にある場合

この場合はJavaScriptを使うこともなく、CSSのみで実装可能です。
まずはヘッダーが固定されていないデフォルトの状態をコーディングしていきます。

<!-- ヘッダー -->
<header>
  <div class="header_wrap">
    <h1>Site Name</h1>
    <nav id="nav">
      <ul>
        <li><a href="#">HOME</a></li>
        <li><a href="#">HOME</a></li>
        <li><a href="#">HOME</a></li>
        <li><a href="#">HOME</a></li>
        <li><a href="#">HOME</a></li>
      </ul>
    </nav>
  </div>
</header>

<!-- メイン -->
<main>
  <div class="contents"></div>
</main>
/* ヘッダー */
header{
  background-color: black;
}

.header_wrap{
  display: flex;
  max-width: 1000px;
  padding: 5px 0;
  margin: 0 auto;
  justify-content: space-between;
  align-items: center;
  color: white;
}

nav{
  ul{
    margin: 0;
    text-align: center;
    li{
      display: inline-block;
      padding: 5px 10px;
      a{
        color: white;
        font-weight: bold;
      }
    }
  }
}

/* メイン */
.contents{
  height: 5000px;
  background-color: red;
}

グローバルメニューが一番上にある場合はヘッダーに含まれていることが多く、また、ヘッダーごとスクロールに合わせて移動することがほとんどなので今回そのように実装していきます。

また、ヘッダーが移動しているか分かりやすいようにmainタグの中にcontainerクラスを与えたdivタグを用意して、その要素に対してheight:5000pxを指定しています。これでスクロールできるだけの十分な高さを確保できます。

現段階でスクロールすると、ヘッダーが置いてきぼりとなり次第に見えなくなってしまう状態だと思います。

これをスクロールさせても画面の一番上にヘッダーが固定された状態にしていきます。

結論としてはpositonプロパティにfixedを指定してあげます。

header{
  background-color: black;
  /* 追加 */
  position: fixed;
  width: 100%;
  top: 0;
  z-index: 1;
}

ただ、position: fixed;を指定しただけではデザインが崩れてしまいます。

というのもそれまで親要素いっぱいまで広がっていた該当要素のwidthプロパティがposition: fixed;を与えることで該当要素の子要素のwidth分までのwidthになってしまいます。

上記の問題を解決するために該当要素にwidth: 100%;を指定してあげます。

また、画面の一番上に固定させるためにtop: 0;の指定と一番前に表示されるようにz-index: 1;を指定します。

これでスクロールに合わせて、ヘッダーがそのままの位置で移動してくれるようになりました。

グローバルメニューが画面の途中にある場合

グローバルメニューが途中に存在する場合は上記の方法ではうまく実装することができません。

まずはグローバルメニューがスクロールに合わせて移動しないデフォルトの状態をコーディングし確認しましょう。

<!-- ヘッダー -->
<header>
  <div class="header_wrap">
    <h1>Site Name</h1>
    <nav id="nav">
      <ul>
        <li><a href="#">HOME</a></li>
        <li><a href="#">HOME</a></li>
        <li><a href="#">HOME</a></li>
        <li><a href="#">HOME</a></li>
        <li><a href="#">HOME</a></li>
      </ul>
    </nav>
  </div>
</header>

<!-- メイン -->
<main>
  <div class="contents"></div>
</main>
/* ヘッダー */
.header_wrap{
  text-align: center;
  color: red;
  h1{
    margin-bottom: 0;
  }
}

/* グローバルメニュー */
#nav{
  background-color: black;
  li{
    display: inline-block;
    padding: 5px 10px;
    a{
      font-size: 20px;
      color: white;
    }
  }
}

/* メイン */
.contents{
  height: 5000px;
  background-color: red;
}

HTMLのコードは先ほどとほとんど同じですね。JavaScriptで扱いやすいようにnavタグにid属性の値としてnavを与えています。また、CSS(Sass)のコーディングを変えて、デザインを変更しています。

先ほどのものはヘッダー全体をスクロールに合わせて移動させていましたが、今回は背景が黒色のグローバルメニューの部分だけを移動させます。

今回、移動させたい要素が画面の途中にあるため、先ほどのようにいきなり画面の上部に固定するようにしてしまうとデザインが崩れてしまいます。

デザインが崩れないようにスクロールに合わせて移動させるには、スクロールして画面上部と移動させたい要素(今回はグローバルメニュー)の上部が重なるときに移動を開始するようにすることで実現したいことができます。

これを実現するにはCSSだけではなく、JavaScript(jQuery)も使っていきます。

まずはコーディングを行い、解説していきます。

/* 追記 */
.fixed{
  position: fixed;
  top: 0;
  width: 100%;
  z-index: 1;
}
// ヘッダー追従
var offset = $('#nav').offset();
$(window).scroll(function(){
  if($(this).scrollTop() > offset.top){
    $('#nav').addClass('fixed');
  }else{
    $('#nav').removeClass('fixed');
  }
});

まず、CSSに画面上部に要素を固定するためのfixedクラスを用意します。

offsetメソッドで#nav要素の表示位置を取得し、変数offsetに代入します。

その後、windowに対してスクロールイベントを設置しています。スクロールイベントでは画面縦のスクロール量が#nav要素表示位置の上部を超えた場合に、#nav要素にfixedクラスを与えて、画面縦のスクロール量がそれ以下の時にはfixedクラスを外すようにしてあげます。

こうすることで画面上部がグローバルメニューの上部の位置と重なるときにはスクロールしても画面上部にグローバルメニューが固定されるように、スクロールに合わせて移動するような動きが実装出来ました。

まとめ

CSSとJavaScript(jQuery)のみで簡単に実装出来ましたね。また、コピペでも実装できるので、ぜひ自分のサイトなどでも実装してみてください。

-プログラミング

Copyright© みぎさんドットコム , 2021 All Rights Reserved Powered by STINGER.