jQueryでドロップダウンメニューを実装する
jQueryでドロップダウンメニューを実装してみます。
ドロップダウンメニューとは
プルダウンメニューとも呼ばれます。Webに限らずソフトウェアやアプリなど様々な場面でよく見かけるUIの一種です。
プルダウンメニューとは、ソフトウェアやWebサイトなどにおけるメニューの表示方法の一種で、クリックなどの操作によって複数のメニュー項目を表示させるタイプの表示方法のことである。
ロールスクリーンを下ろすような動作で展開されるため「プルダウン」や「ドロップダウン」などと呼ばれている。
成果物
1からCSSを書くのは時間がかかるので Bootstrap5 のCSSをお借りました。
操作形態が異なるため、PCではマウスオーバー、モバイルではタップで展開するような仕様となっております。
ナビゲーションの仕様について
ブラウザ幅が768px以上であればリンクは折りたたまずに横並びで表示します。
ブラウザ幅が767.98px以下であれば、リンクを折りたたんで縦並びで表示します。
ドロップダウンメニューの仕様について
ブラウザ幅が768px以上であればリンクにマウスポインタが重なった際に展開を行います。
ブラウザ幅が767.98px以下であれば、リンクをクリックした際に展開を行います。
必要なHTMLを記述
全体のHTML
ナビゲーションも含めた全体のHTMLとなります。
まるごとコピペ頂いて問題ありません。
<nav class="navbar navbar-expand-md navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown navbar-dropdown">
<a
class="nav-link dropdown-toggle navbar-dropdown-toggle"
href="#"
role="button"
>
Dropdown
</a>
<ul class="dropdown-menu navbar-dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider" /></li>
<li>
<a class="dropdown-item" href="#">Something else here</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
ドロップダウンメニューの動作に必要なHTML
PCでは .navbar-dropdown
にマウスポインタが重なるとドロップダウンメニューが展開します。.navbar-dropdown-toggle
にイベントリスナーを設定してしまうと、展開したドロップダウンメニューに
マウスポインタを移動させた際に非表示となってしまいます。
モバイルでは.navbar-dropdown-toggle
にクリックされるとドロップダウンメニューが展開します。.navbar-dropdown
にイベントリスナーを設定してしまうと、展開したドロップダウンメニューをクリックした際に
非表示となってしまいます。
PCではドロップダウンメニュー全体、モバイルではリンク項目にだけイベントリスナーを設定しているイメージです。
<li class="nav-item dropdown navbar-dropdown">
<a
class="nav-link dropdown-toggle navbar-dropdown-toggle"
href="#"
role="button"
>
Dropdown
</a>
<ul class="dropdown-menu navbar-dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider" /></li>
<li>
<a class="dropdown-item" href="#">Something else here</a>
</li>
</ul>
</li>
必要なJavaScriptを記述
まるごとコピペ頂いて問題ありませんが、
1行目から3行目については ES modules の記法となるため、
不要であれば削除頂いても問題ありません。
import $ from "jquery";
import "bootstrap/dist/css/bootstrap.min.css";
import "./index.css";
/**
* ナビゲーションの開閉処理を有効化
*/
const enableNavBarToggle = () => {
$(".navbar-toggler").on("click", function () {
$(".navbar-collapse").slideToggle();
});
};
/**
* ナビゲーションの開閉処理を無効化
*/
const disableNavBarToggle = () => {
$(".navbar-toggler").off();
};
/**
* ナビゲーション内のドロップダウンメニューを有効化
*
* stop()
* 第一引数: 現在のアニメーションをゴールまでジャンプさせるか否か
* 第二引数: 待機状態のアニメーションを破棄するか否か
*/
const enableDropDownMenuNavBar = () => {
$(".navbar-dropdown-menu").hide();
$(".navbar-dropdown").on({
mouseover: function () {
$(this).find(".navbar-dropdown-menu").stop(false, true).slideDown(300);
},
mouseleave: function () {
$(this).find(".navbar-dropdown-menu").stop(false, true).slideUp(300);
},
});
};
/**
* ナビゲーション内のドロップダウンメニューを無効化
*/
const disableDropDownMenuNavBar = () => {
$(".navbar-dropdown-menu").hide();
$(".navbar-dropdown").off();
};
/**
* ナビゲーション内のプルダウンメニュー処理を有効化
*/
const enablePullDownMenuNavBar = () => {
$(".navbar-dropdown-toggle").on("click", function () {
$(this).next().slideToggle();
});
};
/**
* ナビゲーション内のプルダウンメニュー処理を無効化
*/
const disablePullDownMenuNavBar = () => {
$(".navbar-dropdown-toggle").off();
};
/**
* 画面幅によって有効化と無効化する処理を振り分け
*/
const mediaQueryList = window.matchMedia("(max-width: 767.98px)");
const listener = (event) => {
if (event.matches) {
// 767.98px以下
disableDropDownMenuNavBar();
enableNavBarToggle();
enablePullDownMenuNavBar();
} else {
// 768px以上
disableNavBarToggle();
disablePullDownMenuNavBar();
enableDropDownMenuNavBar();
}
};
mediaQueryList.addEventListener("change", listener);
/**
* 処理の開始
*/
$(function () {
listener(mediaQueryList);
});
ブラウザ幅の取得について
resize
はブラウザに負担がかかるため、間引き処理を実装する必要が出てきます。
$(window).on('load resize', function(){
// 処理を記述
});
そのため、ブラウザ幅がブレイクポイントより 大きく or 小さく なったときに1度だけ実行されるwindow.matchMedia
をここでは使用しています。
const mediaQueryList = window.matchMedia("(max-width: 767.98px)");
const listener = (event) => {
if (event.matches) {
// 767.98px以下
} else {
// 768px以上
}
};
mediaQueryList.addEventListener("change", listener);
イベントの登録について
今回は on
メソッドを使用して実装していますが、hover
メソッドを使用して実装することも可能です。
$(".navbar-dropdown").hover(
function() {
// mouseover
$(this).find(".navbar-dropdown-menu").stop(false, true).slideDown(300);
}, function() {
// mouseleave
$(this).find(".navbar-dropdown-menu").stop(false, true).slideUp(300);
}
);
最後に
毎回ググってスクラッチで実装するのは時間の無駄なため、
記事として登録してすぐに参照できるように致しました。
実案件ではこのような仕様で実装をよく行うため、
よろしければご活用ください。