メガメニューのホバー時に表示するタイミングを遅らせる

ヘッダーにホバーで開閉するメガメニューを設置した際、アドレスバーからページ内コンテンツにカーソルを移動したタイミングなど、意図しない形でメニューが開いてしまうことがあります。
その対策として、メガメニュー開閉のタイミングを即時ではなく一定時間遅らせる実装を行ってみます。

サンプルコード

まずは対応前のサンプルで、CSSでの開閉を実装してみます。

<header class="header">
	<div class="logo">サイト名</div>
	<nav class="nav">
		<ul class="nav-lv1">
			<li class="nav-lv1_item">
				<a href="">AAAAA</a>
				<ul class="nav-lv2">
					<li class="nav-lv2_item"><a href="">AAAAA-1</a></li>
					<li class="nav-lv2_item"><a href="">AAAAA-2</a></li>
					<li class="nav-lv2_item"><a href="">AAAAA-3</a></li>
				</ul>
			</li>
			〜 略 〜
		</ul>
	</nav>
</header>

.nav-lv1_itemにホバーした際に、.nav-lv2を表示するようにします。
コードは必要な部分のみ抜粋しているので、メガメニュー部分のコードはデモページでご確認ください。

.nav-lv2 {
	display: none;
}
.nav-lv1_item:hover .nav-lv2 {
	display: block;
}

これでメガメニューの実装ができました。
CSSでのメガメニューのデモページ

実際に確認するとわかりますが、ブラウザの上部から下部にカーソルを移動した際、意図しないタイミングででメガメニューが開かれます。
今回のデモだとそこまで気にならないですが、開かれたメガメニュー内の高さがある場合はユーザーの操作の邪魔になる懸念があります。

その対策として、メガメニューの開閉のタイミングを遅らせるようにしてみます。
タイミングを遅らせるのはJavaScriptを使用するので、まずはCSSでホバーの設定を行なっていたのをJavaScriptで行うように変更します。

イベント対象の.nav-lv1に対してjs操作用のclassを追加します。

<header class="header">
	<div class="logo">サイト名</div>
	<nav class="nav">
		<ul class="nav-lv1">
			<li class="nav-lv1_item js-megamenu-item">
				<a href="">AAAAA</a>
				<ul class="nav-lv2">
					<li class="nav-lv2_item"><a href="">AAAAA-1</a></li>
					<li class="nav-lv2_item"><a href="">AAAAA-2</a></li>
					<li class="nav-lv2_item"><a href="">AAAAA-3</a></li>
				</ul>
			</li>
			〜 略 〜
		</ul>
	</nav>
</header>

CSSの:hoverで表示切り替えしていたのを、classの付け替えで切り替えるように変更します。

.nav-lv2 {
	display: none;
}
.nav-lv1_item.is-hover .nav-lv2 {
	display: block;
}

JavaScriptでホバー時・マウスアウト時にclassを出し分けるように設定します。

const megamenuNav = document.querySelectorAll('.js-megamenu-item');

for (let i = 0; i < megamenuNav.length; i++) {
  megamenuNav[i].addEventListener('mouseover', megamenu_over);
  megamenuNav[i].addEventListener('mouseleave', megamenu_leave);
}

function megamenu_over(e) {
  this.classList.add('is-hover');
}
function megamenu_leave(e) {
  this.classList.remove('is-hover');
}

これでJavaScriptで最初のデモと同じ挙動ができました。
JavaScriptでのメガメニューのデモページ

ホバー時・マウスアウト時に一定時間開閉を行わない対応を追加します。

const megamenuNav = document.querySelectorAll('.js-megamenu-item');

for (let i = 0; i < megamenuNav.length; i++) {
  megamenuNav[i].addEventListener('mouseover', megamenu_over);
  megamenuNav[i].addEventListener('mouseleave', megamenu_leave);
}

let megamenuOverTimer; // ホバー時にナビを開くタイマー
let megamenuLeaveTimer; // マウスアウト時にナビを閉じるタイマー
function megamenu_over(e) {
  let t = this;
  // ナビを開くタイマーをキャンセル
  clearTimeout(megamenuOverTimer);
  // ホバーしたナビが開いている場合
  if(t.classList.contains('is-hover')) {
    // ナビを閉じるタイマーをキャンセル
    clearTimeout(megamenuLeaveTimer);
  // ホバーしたナビ以外が開いている、またはいずれも開いていない場合
  } else {
    // 一定時間後にナビを開く
    megamenuOverTimer = setTimeout(function() {
      t.classList.add('is-hover');
    }, 1000);
  }
}
function megamenu_leave(e) {
  let t = this;
  // ナビを開くタイマーをキャンセル
  clearTimeout(megamenuOverTimer);
  // マウスアウトしたナビが開いていた場合
  if(t.classList.contains('is-hover')) {
    // 一定時間後にナビを閉じる
    megamenuLeaveTimer = setTimeout(function() {
      t.classList.remove('is-hover');
    }, 1000);
  }
}

これで開閉のタイミングを遅らせたメガメニューの実装ができました。
実装内容に関してはコメントに記載している通りです。
メガメニューの開閉を遅らせるデモページ
挙動がわかりやすいように1000ミリ秒で設定していますが、実際には300程度にするとちょうどいいと思います。

jQuery版は以下になります。

$(function() {
  let megamenuOverTimer; // ホバー時にナビを開くタイマー
  let megamenuLeaveTimer; // マウスアウト時にナビを閉じるタイマー
  $('.js-megamenu-item').on({
    mouseenter: function(e) {
      let t = $(this);
      // ナビを開くタイマーをキャンセル
      clearTimeout(megamenuOverTimer);
      // ホバーしたナビが開いている場合
      if(t.hasClass('is-hover')) {
        // ナビを閉じるタイマーをキャンセル
        clearTimeout(megamenuLeaveTimer);
      // ホバーしたナビ以外が開いている、またはいずれも開いていない場合
      } else {
        // 一定時間後にナビを開く
        megamenuOverTimer = setTimeout(function() {
          t.addClass('is-hover');
        }, 1000);
      }
    }, mouseleave: function(e) {
      let t = $(this);
      // ナビを開くタイマーをキャンセル
      clearTimeout(megamenuOverTimer);
      // マウスアウトしたナビが開いていた場合
      if(t.hasClass('is-hover')) {
        // 一定時間後にナビを閉じる
        megamenuLeaveTimer = setTimeout(function() {
          t.removeClass('is-hover');
        }, 1000);
      }
    }
  })
});

jQuery版のメガメニューの開閉を遅らせるデモページ

このエントリーをはてなブックマークに追加

関連記事

コメントを残す

メールアドレスが公開されることはありません。
* が付いている欄は必須項目です

CAPTCHA


コメントが承認されるまで時間がかかります。

2024年4月
 123456
78910111213
14151617181920
21222324252627
282930