本文へスキップ
Build

Column

コラム

ハンバーガーメニューをjQueryで実装する方法と現場での選択基準

この記事には広告リンクを含みます。紹介している商品・サービスの一部はアフィリエイトプログラムを利用しています。 商品・サービスの選定はご自身の判断でお願いいたします。

ハンバーガーメニューをjQueryで実装する方法と現場での選択基準 のアイキャッチ

スマホでサイトを開き、ハンバーガーアイコンをタップしても何も起きない。
こうした実装トラブルは、コーディング現場でよく出会います。
実装自体は難しくありませんが、WordPressの読み込み順序やvanilla JSとの使い分けで詰まるケースが多い印象です。
この記事では、jQueryによる最小実装と、WordPressならではの二重読み込み回避策、そしてvanilla JSとの選択基準を整理します。
コピペで動くコードより、「なぜそう書くか」の判断軸を持って帰ってください。

jQueryでハンバーガーメニューを実装する最小コード

jQueryでハンバーガーメニューを動かすには、クラスのトグルとaria-expandedの管理が核になります。
コードを書く前に、マークアップの選択が動作品質を左右します。

button要素を使う理由

ハンバーガーボタンは<div>ではなく<button>要素で作ってください。
<div>はキーボードのTabキーでフォーカスが当たらず、スクリーンリーダーにも「ボタン」として認識されません。
<button>ならブラウザがデフォルトでフォーカスを当て、Enterキーでも発火します。
アクセシビリティの基本であると同時に、実装ミスを防ぐ手堅い選択です。
aria-expanded属性は、メニューの開閉状態をスクリーンリーダーに伝えます。
trueでメニュー展開中、falseで閉じていることを示します。

<button class="menu-toggle" aria-expanded="false" aria-controls="nav-menu">
  <span class="bar"></span>
  <span class="bar"></span>
  <span class="bar"></span>
</button>
<nav id="nav-menu" hidden>
  <ul>
    <li><a href="&quot;#about&quot;&gt;About&lt;/a&gt;&lt;/li&gt;"
    <li><a href="&quot;#service&quot;&gt;Service&lt;/a&gt;&lt;/li&gt;"
    <li><a href="&quot;#contact&quot;&gt;Contact&lt;/a&gt;&lt;/li&gt;"
  </ul>
</nav>

×変形アニメーションはCSSだけで完結

三本線を×マークに変形するアニメーションは、CSSのみで実現できます。
JavaScriptで直接スタイルを書き換える必要はありません。
クラスを付け外しして、CSS側でトランジションを受け取る構成が保守しやすいです。

.menu-toggle .bar {
  display: block; width: 24px; height: 2px;
  background: #333;
  transition: transform 0.3s, opacity 0.3s;
}
.menu-toggle.is-open .bar:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.menu-toggle.is-open .bar:nth-child(2) { opacity: 0; }
.menu-toggle.is-open .bar:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

jQueryのコードはクラス管理と属性更新に絞ります。
開いたメニューでページ内リンクを押してもメニューが閉じない問題は、ナビ内アンカーへのクリックイベント追加で解決できます。
この処理を入れていない実装は現場でよく見かけます。

$(function () {
  var $toggle = $('.menu-toggle');
  var $nav    = $('#nav-menu');

  $toggle.on('click', function () {
    var expanded = $(this).attr('aria-expanded') === 'true';
    $(this).attr('aria-expanded', !expanded).toggleClass('is-open');
    $nav.prop('hidden', expanded);
  });

  // ページ内リンクでメニューを閉じる
  $nav.find('a').on('click', function () {
    $toggle.attr('aria-expanded', 'false').removeClass('is-open');
    $nav.prop('hidden', true);
  });
});

WordPressでjQueryを使うとき、CDN追加が不要な理由

WordPressサイトでjQueryを使う場合、CDNからの追加読み込みは基本的に不要です。
自分が触れてきた範囲では、WordPressテーマがjQueryをすでに読み込んでいるケースがほとんどです。
自分で<script>タグやCDNリンクを追加すると、同じライブラリが2回読み込まれて競合が起きます。

二重読み込みのよくある症状:$ is not definedCannot read properties of undefined がコンソールに出る

対処の前に、ブラウザの開発者ツール(ネットワークタブ)でjQueryが何回読まれているか確認してください。
1回だけなら追加不要、2回以上あれば競合が疑われます。
自分がWordPress案件で最初にやることのひとつが、このチェックです。

WordPressでJSファイルを安全に追加するには、wp_enqueue_scriptを使ってください。
依存配列に'jquery'を指定するだけで、読み込み順序をWordPressが保証します。

// functions.php
function my_theme_scripts() {
  wp_enqueue_script(
    'my-menu',
    get_template_directory_uri() . '/js/menu.js',
    ['jquery'],   // jQueryへの依存を宣言
    '1.0.0',
    true           // フッターに出力
  );
}
add_action('wp_enqueue_scripts', 'my_theme_scripts');

テーマ側のjQueryをそのまま流用でき、追加ファイルだけを読み込む構成になります。
CDNリンクを直書きする方法と比べて、バージョン管理とキャッシュ制御も楽になります。
WordPress案件では、まずこの方法から試してください。

jQuery vs vanilla JS:案件スタックで選ぶ判断基準

ハンバーガーメニュー程度の実装なら、vanilla JSで十分に書けます。
それでも現場でjQueryを使う理由は「すでに入っているから」がほとんどです。
自分の案件では、以下の基準で判断しています。

環境

選択

理由

WordPress(テーマ依存あり)

jQuery

追加コストなし、競合なし

既存jQueryプラグイン多用

jQuery

統一で保守しやすい

Astro / Next.js など

vanilla JS

jQueryのバンドルコストが割に合わない

小規模LP・新規静的案件

vanilla JS

依存を増やさず軽量に保てる

WordPressの場合、テーマが読み込むjQueryをそのまま使えるため追加コストが実質ゼロです。
プラグインとの統一感もあり、保守を別の人に引き継ぐときも迷いにくい選択です。

Astro環境でjQueryを使おうとすると、npm install jqueryしてバンドル設定を変える手順が必要になります。
自分がAstroで初クライアント案件を対応したとき、モジュール解決まわりで想定外の手間が増えました。
モダン環境ではdocument.querySelectorclassList.toggleで同じ動作を書けるため、jQueryを入れる理由がほとんどありません。
Astro環境での技術選定についてはAstroとWordPressの使い分け:迷わない3つの判断基準も参考にしてください。

vanilla JSで書く最小実装は以下です。
jQueryとほぼ同じ構造なので、切り替えのハードルは高くありません。

const toggle = document.querySelector('.menu-toggle');
const nav    = document.querySelector('#nav-menu');

toggle.addEventListener('click', () => {
  const expanded = toggle.getAttribute('aria-expanded') === 'true';
  toggle.setAttribute('aria-expanded', String(!expanded));
  toggle.classList.toggle('is-open');
  nav.hidden = expanded;
});

nav.querySelectorAll('a').forEach(link => {
  link.addEventListener('click', () => {
    toggle.setAttribute('aria-expanded', 'false');
    toggle.classList.remove('is-open');
    nav.hidden = true;
  });
});

実装後のチェックとして、スマホでメニューが3タップ以内で完結するか確認してください。
自分は問い合わせページへの導線を必ずスマホ実機で確認します。
ハンバーガーの開閉アニメーションが重いとそれだけで離脱につながります。
コードの動作確認と合わせて、導線の軽さも見てください。

まとめ

  • jQueryの最小実装はtoggleClassaria-expanded管理の組み合わせ
  • ×変形アニメーションはCSSだけで完結
  • WordPressではCDN追加不要、wp_enqueue_scriptの依存宣言で安全に読み込む
  • Astroなどのモダン環境ではvanilla JSが適切、jQueryのバンドルコストは割に合わない
  • 実装後はスマホでの3タップ導線チェックを忘れずに

コーディング代行・実装判断で詰まったら Build に振ってください。