jQueryでナビゲーションメニュー(スティッキーヘッダー)の実装方法

jQueryでナビゲーションメニュー(スティッキーヘッダー)の実装方法

今回は、jQueryでナビゲーションメニュー(スティッキーヘッダー)の実装方法につきまして、実際にサンプルコードを用いて、詳しく記載していこうと思います。

ウィンドウのスクロールに応じてヘッダーを移動させる「ナビゲーションメニュー(スティッキーヘッダー)」の作成方法を説明します。ページをスクロールしていくと、ヘッダーが表示領域の上部に張り付いたように表示させる方法になります。比較的簡単に実装することが可能になります。

という事で、それでは今回はッ、

  • ・ナビゲーションメニュー(スティッキーヘッダー)の概要
  • ・ナビゲーションメニューのHTMLとCSS
  • ・スティッキーヘッダーのjQuery(JavaScript)

上記について記載していこうと思います…。

jQueryでナビゲーションメニュー(スティッキーヘッダー)の実装方法1
サンプルDEMOページ

ナビゲーションメニュー(スティッキーヘッダー)の概要

Webページのヘッダー部分には、「ナビゲーション」や「検索フォーム」など、ページを利用するうえで重要な役割を担う部分が配置されることが多くなることと思います。こういったレイアウトの場合、1ページが長くなるとページ下部から上部への移動が面倒に感じることとなります。

この問題の解決方法の1つが今回ご説明する「スティッキーヘッダー」です。スティッキーヘッダーとは、ウィンドウのスクロールに合わせて移動するヘッダーです。極端に1ページが長くなっても、容易にヘッダーに配置した部分を利用できるようになります。例えば、グローバルナビゲーションをスティッキーヘッダーにすれば、いつでもすぐに別のページにジャンプできるようになります。

jQueryでナビゲーションメニュー(スティッキーヘッダー)の実装方法2

ワークフロー

スティッキーヘッダーを実装するためには、ウィンドウのスクロールの状態を監視したうえで、スクロール量に応じてヘッダーのスタイルを切り替えることが必要になります。具体的には以下の流れで処理をおこなっていきます。

  • ①ヘッダーのデフォルトの位置を保存する
  • ②ウィンドウのスクロール量を常に監視する
  • ③ウィンドウのスクロール量がヘッダーのデフォルト位置を超えた場合、スティッキー配置にする
  • ④ウィンドウのスクロールが画面上部に戻ったら、ヘッダーをデフォルトの位置に戻す

ナビゲーションメニューのHTMLとCSS

スティッキーヘッダーは、CSSのpositionプロパティを操作することによって実現します。まずは、HTMLとCSSを記述してみます。

サンプルHTML<header class=”page_header”>
<div class=”inner”>
<h1 class=”main_logo”>
<a href=”#”>
<img src=”./images/logo.png” alt=”MK-design” height=”50″ width=”115″>
</a>
</h1>
<nav class=”primary_nav”>
<ul>
<li><a href=”#”>menu.1</a></li>
<li><a href=”#”>menu.2</a></li>
<li><a href=”#”>menu.3</a></li>
<li><a href=”#”>menu.4</a></li>
</ul>
</nav>
</div>
</header>

HTMLでは上記のとおり、<header class=”page_header”>にロゴとナビゲーションが含まれています。この.page_headerクラスが指定されている要素をスティッキーにします。

続いてCSSを記述してみますが、とてもシンプルなスタイルになります。

*/ デフォルトスタイル */
.page_header {
background-color: rgb(255,255,255);
position: absolute;——①
width: 100%;
min-width: 980px;
box-shadow: 0 1px 1px rgba(0,0,0,.25);
}
*/ スティッキースタイル */
.page_header.sticky {——②
position: fixed;——③
top: 0;

}
.page_header > .inner {
margin: auto;
width: 980px;
}

まず、要素をスティッキー化するとその要素分のスペースが空になってしまう為、①あらかじめposition: absolute;を指定しておくことで、全体のレイアウトに影響しないようにしておきます。
また、.page_header.stickyというセレクタが記述してありますが②、この.stickyクラスはHTMLには記述しません。ウィンドウのスクロールがヘッダーのデフォルト位置を上回ったらjQueryによって追加されるクラスになります。

上記CSSで重要なのは、positionプロパティになります。初期状態では「absolute」が指定されていますが、スティッキー時には「fixed」を③指定しています。
このように、初期状態とスティッキー時の2つの状態のスタイルをあらかじめCSSで定義しておき、状況に応じてjQueryからHTMLのclass属性を操作することでスタイルを有効化する、という仕組みになります。

jQueryでナビゲーションメニュー(スティッキーヘッダー)の実装方法3

スティッキーヘッダーのjQuery(JavaScript)

それでは、スティッキーヘッダーを実現するjQueryのコードを記載してみます。

サンプルscript$(function() {
$(“.page_haeder”).each(function(){
// ここから① //
var window = $(window),
header = $(this),
headerOffsetTop = header.offset().top;
// ここまで① ここから② //
window.on(“scroll”,function(){
if(windoow.scrollTop() > headerOffsetTop) {
header.addClass(“sticky”);
} else {
header.removeClass(“sticky”);
}
});
// ここまで② ここから③ //
window.trigger(“scroll”);
// ここまで③ //
});
});

全体が$(“.page_haeder”).each(function(){});で囲まれています。これはjQueryがHTMLの中から.page_headerというクラスの要素を探してきて、その要素にたいしてこの括弧内の処理を実行する、という処理になります。

全体の処理は大きく分けて3つに分類することができます。
・変数の準備①
・ウィンドウのスクロールイベントを監視する処理②
・ウィンドウのスクロールイベントを発生させる処理③

変数の準備

スティッキーヘッダーに関する一連の処理で必要になる要素を変数に代入します。今回は3つの変数を定義しています。

var window = $(window), //ウィンドウをjQueryオブジェクト化
header = $(this), //ヘッダーをjQueryオブジェクト化
headerOffsetTop = header.offset().top; //ヘッダーのデフォルト位置を取得

変数windowには$(window)を代入(格納)していますが、この「window」は「Windowオブジェクト」といい、ブラウザのウィンドウを表すJavaScriptオブジェクトです。ウィンドウを監視もしくはスクロール量に応じてjQueryを利用するには、WindowオブジェクトをjQueryオブジェクト化する必要があります。それがこの$(window)になります。

続いて、変数headerにはHTMLのヘッダーにあたる.page_headerのjQueryオブジェクトを格納しています。(thisには、.page_headerが格納されています)。

最後に変数headerOffsetTopには「ドキュメント上端からの距離」を格納しています。offset()メソッドは「jQuery要素のドキュメント上の位置を取得するメソッド」です。以下ふたつのプロパティをもっています。

プロパティ 説明
top ドキュメントの上端からの距離
left ドキュメントの左端からの距離

ウィンドウのスクロールイベントを監視する処理

変数の準備ができたので、続いてスティッキーヘッダーの処理を説明いたします。

window.on(“scroll”,function(){——①
if(windoow.scrollTop() > headerOffsetTop) {——②
header.addClass(“sticky”);——③
} else {
header.removeClass(“sticky”);——④
}
});

windowオブジェクトをjQuery化した変数windowに対してon()メソッドを呼び出しています。第1引数にscrollを指定している①ので、、第2引数の処理は「スクロールイベント」が発生した際に実行されます。

on()メソッドに渡した関数では、最初にウィンドウの「スクロール量」を調べています②。scrollTop()メソッドは「要素がスクロール可能な場合に、その要素が縦方向にどれだけスクロールしたかを調べるメソッド」です。この値とあらかじめ保存しておいたヘッダーの初期状態の位置を比較し、ウィンドウがヘッダーの初期状態の位置よりも下方へスクロールされている場合はHTMLのヘッダーに、.stickyというクラスを追加し③、そうでなければ削除しています④。

addClass()とremoveClass()は対の関係にあるjQueryのメソッドです。ともにHTMLのclass属性を操作します。addClass()メソッドは引数に渡したクラス名をHTMLに追加し、removeClass()メソッドは削除します。

スクロールイベントはなんども発生するため、.stickyクラスの記述の有無にかかわらずaddClass()メソッドが何度も呼ばれることになりますが、これによってエラーになることはありません。jQueryが内部的に「そのクラスがなければ追加する」という処理をおこなっているためです。
スティッキーのコードはほぼ完成ですが、最後に「ウィンドウのスクロールイベントを発生させる処理」を追加します。

ウィンドウのスクロールイベントを発生させる処理

ページの途中でブラウザをリロードした場合でもヘッダーをスティッキー配置するための処理です。ここでは先ほど設定したスクロールイベントをプログラム側から発生させます。

window.trigger(“scroll”);

trigger()メソッドは「任意のイベントを発生させるメソッド」です。この引数に「”scroll”」を指定することで、Windowオブジェクトにスクロールイベントを発生させています。本来、スクロールイベントはユーザーが操作しない限り発生しませんが、このように記述することで、イベントを任意のタイミングで発生させることが可能です。

なぜこのような処理を追加しているかというと、「画面の途中までスクロールした状態でブラウザをリロードした場合」や「ページ内のフラグイベント識別子(id)に直接アクセスした場合」のような「画面スクロールは行われていないが、表示状態としてはスティッキー化すべき状況」において、スティッキーヘッダーを動作させるためです。上記の処理を追加することで、こういった状況に対処できます。

なお、ここでは「スクロールイベントを発生させる」と表現していますが、実際に画面をスクロールするわけではありません。プログラム側からブラウザに対して「スクロールイベントが発生した」と伝える処理が行われているだけです。

スクロールイベントが発生すると「ウィンドウのスクロールイベントを監視する処理」が行われるため、スティッキーヘッダーを実現できます。これで完成になります。

今回のスティッキーヘッダーのように、状況別・状態別のスタイルをあらかじめCSSに複数定義しておき、実際にHTMLに適用するスタイルは、jQueryでHTMLの属性を操作することで決定する、という仕組みはとても重要です。

JavaScriptやjQueryを使用するとスタイルの値そのものも変更できますが、そうすると同じ要素のスタイルがCSSとJavaScriptに分散されることになるため、メンテナンスが困難になってしまいます。HTML、CSS、JavaScriptのそれぞれにどのような役割を担当させるべきかを常に意識しながら、適切な連携を保つことが大切になります。

ということで今回は、jQueryでナビゲーションメニュー(スティッキーヘッダー)の実装方法につきまして、サンプルコードを交え記載いたしました。

スティッキーヘッダー便利ですね。個人的にはjQueryとCSSの両方でコーディングを行うことがございます。少し説明すると、CSSでposition: sticky;を指定すれば、スティッキーヘッダーが簡単に実装することが可能ですが、IEには対応していないCSSになります。そこで、スマートフォン用CSSでは、position: sticky;、PC用ではjQueryで条件分岐をおこない上記のコードのように指定することが多々ございます。また、これにつきまして詳しくは別記事に記載しようと思います。

とりあえず、今回はここまで…。

お仕事のご依頼は↓コチラより…、それではまた次回…。