【コピペ可】ハンバーガーメニューを3行のjQueryで実現する

ウェブサイトに動きをつけよう。3行でできるjquery製ハンバーガーメニュー。

この記事の概要

スマホ版サイトではおなじみのハンバーガーメニューの作り方を3行のjQueryを元に解説します。

この方法を使ったハンバーガーメニューでは、言語ごとにHTMLはデータ、CSSは見た目、javascriptは状態遷移と明確に役割を分担して記述しています。昨今のVueやReactなどにみられるコンポーネント指向にも通ずる考え方ですので、ソースコードの内容も参考にするとよいです。

長く使えるプログラムですので、コピペ用にブックマークしておいてください。

ハンバーガーメニューの完成デモ

まずはハンバーガーメニューのデモになります。HTMLとCSSとjQueryで実装しています。デモのボタンをクリックするとメニューが開き、もう一度押すとメニューが閉じます。スマホサイトでは頻出する定番のUIになります。

See the Pen 最もシンプルなハンバーガーメニュー実装方法01 by YutoSeta / ホームページ制作のエクレア (@yutoseta) on CodePen.

jQueryの実装内容を解説

bodyタグの末尾にCDNのjQueryを読み込みましょう

jQueryを使う際には、scriptタグで事前にjQueryを読み込んでからでないと使えません。以下のCDNを読み込むことでjQueryが使えます。

<script src="https://code.jquery.com/jquery-3.4.1.js" integrity="sha256-WpOohJOqMqqyKL9FccASB9O0KwACQJpFTUBLTYOVvVU=" crossorigin="anonymous"></script>

以下のリンクより、ダウンロードしてから使うこともできます。

jQuery公式サイト
https://code.jquery.com/

jQueryのソースコード

まずは、HTMLやCSSは無視してjQueryのコードのみご覧ください。
ハンバーガーメニューのデモとして実際に使用しているコードになります。

$('.menu-btn').on('click', function(){
    $('.menu').toggleClass('is-active');
});

onメソッドとtoggleClassメソッドでクラスの付け替えをする

jqueryのonメソッドはユーザーの操作を検知して、なんらかの処理を実行します。今回は「.menu-btn」要素のクリックしたときに、toggleメソッドを実行しています。toggleClassメソッドでは「.menu」に「is-active」というクラスの付け外しをしています。is-activeがついている時はメニューが開いている状態、付いていない時はメニューが閉じている状態です。

つまりは、onメソッドとtoggleClassメソッドの組み合わせでクリックによってis-activeクラスの付け替えをしています。

jQueryとCSSの役割分担をしよう

jQuery(javascript)は極力クラスの付け替えのみにして、プログラムをシンプルにする

今回のプログラムでは、メニューボタン(.menu-btn)をクリックしたら、メニュークラス(.menu)に任意のクラス(.is-active)の付け替えを行う、という処理しかjqueryには記述していません。クラスの付け替えのみでメニューの閉じ開きを実現しています。この付け替えするクラス「is-active」はメニューがアクティブな状態(開いている)とそうでない状態(閉じている)を表現するためのクラスになっています。HTMLとCSSが中心のウェブサイトでは、このようにしてjavascriptはなるべくクラスの付け替えだけで実現してあげるとプログラムがシンプルになります

CSSは変化前・変化後の状態を記述する

さて、.menuにis-activeというクラスが付け替えられているわけですが、ここでCSSをみてみましょう。以下の部分がクラスの付け替えによって書き換えられるスタイル部分です。

/*----------------------------
* アニメーション部分
*----------------------------*/
/* アニメーション前のメニューの状態 */
.menu{
  transform: translateX(100vw);
  transition: all .3s linear;
}
/* アニメーション後のメニューの状態 */
.menu.is-active{
  transform: translateX(0);
}

transitionでは、アニメーション前のメニューの状態とアニメーション後のメニューの状態を0.3秒間かけて一定のスピード(linear)で変化させることでアニメーションを実現しています。

アニメーション前のメニューの状態(is-activeクラスが付いていないとき)はtransform:translateX(100vw);で右に画面幅(100vw)分だけずらしています。これでメニューを閉じている時の位置にしています。

アニメーション後のメニューの状態(is-activeクラスがついているとき)はtransform:translateX(0);として右にずれた分を元に戻しています。これでメニューを開いている時の位置にしています。

CSSでアニメーション前のメニューとアニメーション後のメニューを定義して、javascriptのクラスの付け替えでその状態を変化させる。というのがシンプルにハンバーガーメニューを実装するポイントです。

いろいろなメニュー開閉アニメーション

スライドイン(最初のデモと同じ)

/* アニメーション前のメニューの状態 */
.menu{
  transform: translateX(100vw);
  transition: all .3s linear;
}
/* アニメーション後のメニューの状態 */
.menu.is-active{
  transform: translateX(0);
}

フェードイン

See the Pen 最もシンプルなハンバーガーメニュー実装方法02 by YutoSeta / ホームページ制作のエクレア (@yutoseta) on CodePen.

/* アニメーション前のメニューの状態 */
.menu{
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s linear;
}
/* アニメーション後のメニューの状態 */
.menu.is-active{
  pointer-events: auto;
  opacity: 1;
}

くるっと回転しながら現れる

/* アニメーション前のメニューの状態 */
.menu{
  transform-origin: top left;
  transform: rotateZ(-90deg);
  transition: all .3s ease;
}
/* アニメーション後のメニューの状態 */
.menu.is-active{
  transform: rotateZ(0deg);
}

拡大しながら現れる

See the Pen 最もシンプルなハンバーガーメニュー実装方法04 by YutoSeta / ホームページ制作のエクレア (@yutoseta) on CodePen.

/* アニメーション前のメニューの状態 */
.menu{
  pointer-events: none;
  opacity: 0;
  transform-origin: center;
  transform: scale(.5);
  transition: all .3s ease;
}
/* アニメーション後のメニューの状態 */
.menu.is-active{
  pointer-events: auto;
  opacity: 1;
  transform: scale(1.0);
}

まとめ

役割を分担することでjavascriptの記述量を大幅に減らす

今回のような記述をすることでハンバーガーメニューの実装が3行になったように、javascriptの記述量を大幅に減らすことができます。タブメニューやアコーディオンメニュー、プルダウンメニュー、ありとあらゆる動きを伴うUIパーツはこのようなクラスの付け替えのみで再現できるのです。

VueやReactのコンポーネントでも同じです

ユーザーのアクション(イベント)によってコンポーネントの状態を切り替える。コンポーネントの状態が変わることで見た目も変わる。この考え方は昨今のjavascriptフレームワークで用いるコンポーネント指向と同じです。ぜひ、活用していってください。

javascriptのみの実装方法はこの記事を参考にしてください

jQueryを使わない生のJavaScriptでハンバーガーメニューを実現する【コピペ可】jQuery不要!javascriptだけでハンバーガーメニューを実現

17 COMMENTS

Yuto Seta

display:none;を使わずとも画面外にメニューを移動させて待機させておいて、
クリックしたと同時に画面内に現れるようにすることで実現できます。
今回でいうと、
transform: translateX(100vw);
とすることで画面外にメニューが隠れています。
100vwは画面の横幅の大きさを表しています。

返信する
ヨシアツ

レスポンス化するときの、jQuery 側で記述するにはどうしますか?
・レスポンスしない時は綺麗に完成しました。
・「resize]やinnerWidthなど使いましたが、上手くいきませんでした。

返信する
Yuto Seta

loadイベントとresizeイベントの時に、
ロードした時の画面の横幅に応じて、
ハンバーガーメニューのプログラムを読み込んだり、
イベントの紐付けを解除したりすることで、
レスポンシブの場合でも誤動作を防ぐことができますね。
イベントの紐付け解除はjQueryのoffメソッドを使います。
https://api.jquery.com/off/

返信する
ミント

コピペで試させてもらったところ、ハンバーガーメニューをクリックしても表示されませんでした。
検証で確認すると、Sourcesで.Jsファイルが空っぽ(何も書かれていない)状態でした。どこが悪いのかわからずコメントで残させてもらいます。

返信する
Yuto Seta

正しくjavascriptファイルが参照できているか確認してみてください。
参照できていた場合は、
プログラムが空っぽだった場合はエディタで編集したあとファイルを保存していない可能性も検討してみてください。

  1. 1.jQuery本体のプログラムを読み込む
  2. 2.ハンバーガーメニューのプログラムを読み込む

上記の順番でプログラムが読み込まれていれば、大体の場合は動作すると思います。
動作しない原因が検証できないので確実なお答えができず、ごめんなさい?

返信する
こき

リクエストです!
入力フォームによく使われるステッププログレスバーに挑戦しているのですが、
次の項目を表示させたり、バリデート処理するためのJSと混ざってしまい、詰まっています。
同ページで項目の更新に伴って進むプログレスバーの実装方法についてご教授願います!

返信する
eclair.company

リクエストいただけて嬉しいです~?
jsの処理とcssの処理を管理しやすくきちっとわけるのは、
特にそういったリッチなUIをつくると難しいですよね。
VueやReactを使った処理と通常のjavascriptを使った処理で記事にてご紹介できたらと思いますので、今しばらくお待ちください???

返信する
まぴおん

質問よろしいでしょうか?
こちらのハンバーガーメニューから
アンカーリンクでページ内に飛んだ後、再びハンバーガーメニューをタップしてもメニューが開かないのですが、何か原因がわかりませんでしょうか?
こちらサイトのデモではアンカーリンクがなく試すことができず、、、。

返信する
eclair.company

Chromeの検証などを使って、以下のような原因がないか探ってみてください。

  • – メニューボタンの上に別の要素がかぶさっていてクリックできていない
  • – Consoleタブで何かしらのエラーがでている
  • – 別ページのアンカーリンクに遷移していてそこページでjavascriptをそもそも読み込んでいない
返信する
まさ

こちらのハンバーガーメニューでメニュー以外の所をタップすると元の画面に戻るようにするにはどうしたらよいのでしょうか。

返信する
Yuto Seta

以下の手順でプログラムをかいてみるとよいかもしれません。
メニュー本体をクリックしたときにメニューが閉じてしまわないように注意する必要があります。
event.currentTargetをつかって、
メニューの外側の要素をクリックしたときにだけメニューを閉じるプログラムを動作させるのがコツになります。

  1. 1.メニューの本体の外側に画面全体を覆う要素を設置する
  2. 2.そこをクリックしたときにメニューを閉じるように指定のクラスをはずす
返信する
まさ

Yuto Seta様
ご返答ありがとうございます。
追加のリクエストなのですが、メニューが開いているときに「バツ印」に切り替えるためにはどうしたらいいのでしょうか。
実装方法についてご教授をお願いします。

返信する
eclair.company

メニューを「バツ印」に切り替える場合は、
以下のコードでボタンにもメニューの開閉に応じてクラスの付け替えをして、
「.menu-btn.is-active」のときに「バツ印」を表示させてあげると良いと思います。
「バツ印」はアイコン画像でもspanにスタイルを当てるでもどのようなやり方でも構いません。

$('.menu-btn').on('click', function(){
$('.menu').toggleClass('is-active');
$('.menu-btn').toggleClass('is-active');
});

返信する
Noriko

質問失礼いたします。
ハンバーガーメニューを開いていずれかのリンク先にとんだあと、メニューを自動で閉じるにはどうすればよいでしょうか。
現状ですとハンバーガーメニューが開いたままになります。

返信する
YutoSeta

1. 別ページに遷移する場合は、
ページ読み込み時にメニューを閉じてあげると良いかと思います。
2. 同じページのリンクであれば、
リンクをクリックした時にクリックイベントが発火されるので
それを元にメニューを閉じてあげる処理を追加してあげましょう。

返信する

Leave a Reply

Your email address will not be published. Required fields are marked *