ハンバーガーメニューが動かない原因と解決法【Cannot read properties of null】

公開日
最終更新日

いつもどおり書いたはずのハンバーガーメニューが、特定のページだけ動かない——コーディングをしていると出くわす、地味にハマりやすいトラブルです。

結論から言うと、原因は存在しない要素に対してaddEventListenerを実行していることで、コンソールには「Cannot read properties of null」というエラーが出ます。解決策は、要素があるときだけイベントを登録するよう、if文でガードすることです。この記事では、症状・エラー内容・原因・対策を順に解説します。

症状:特定のページだけメニューが動かない

スマホサイトでよく見る「三」のボタン。タップするとメニューが開く、あの仕組みです。該当のコードは次のような形でした。

//hamburger menu
function hamburger() {
  document.getElementById('line1').classList.toggle('active');
  document.getElementById('line2').classList.toggle('active');
  document.getElementById('line3').classList.toggle('active');
  document.getElementById('hamburger-menu').classList.toggle('active');
}
document.getElementById('hamburger').addEventListener('click', function () {
  hamburger();
});

記述ミスがないか何度も見直しても、原因が見つからない。こんなときは、まずブラウザのコンソールを確認するのが近道です。

エラー内容:Cannot read properties of null

デベロッパーツールのコンソールを開くと、次のエラーが出ていました。

Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')

末尾の(reading 'addEventListener')が、どこでつまずいたかを教えてくれています。「nullに対してaddEventListenerを読もうとした」という意味です。

原因:存在しない要素にaddEventListenerした

document.getElementById('hamburger')は、対象のIDを持つ要素が見つからないとnullを返します。今回は、ハンバーガーメニューを使わないページがサイト内にあり、そのページにはid="hamburger"の要素が存在しませんでした。

その結果、nullに対して.addEventListener(...)を呼び出してしまい、エラーが発生していたのです。JavaScriptはnullのプロパティを読めないため、ここで処理が止まります。全ページ共通のJSに書いていたことが、このトラブルの引き金でした。

対策:要素があるときだけ実行する

解決策はシンプルです。取得した要素を変数に入れ、それが存在する(nullでない)ときだけaddEventListenerを実行するよう、if文で囲みます。

//hamburger menu
function hamburger() {
  document.getElementById('line1').classList.toggle('active');
  document.getElementById('line2').classList.toggle('active');
  document.getElementById('line3').classList.toggle('active');
  document.getElementById('hamburger-menu').classList.toggle('active');
}
const hamburgerbtn = document.getElementById('hamburger');
if (hamburgerbtn) {
  hamburgerbtn.addEventListener('click', function () {
    hamburger();
  });
}

if (hamburgerbtn)で、要素が取得できたページでだけイベントを登録します。ハンバーガーメニューがないページではifの中に入らないので、エラーは発生しません。要素の有無にかかわらず、同じJSを全ページで読み込めるようになります。

なぜnullになるのかを知っておく

この対策の背景には、getElementByIdの性質があります。要素が見つかったときはその要素を、見つからなかったときはnullを返す——この仕様を知っていれば、「取得結果はnullかもしれない」と身構えられます。

DOMを取得してから操作するコードは、要素が存在する前提で書きがちです。しかし、全ページ共通のJSでは「このページにその要素はあるか」が常に問われます。取得と操作の間に存在チェックを1つ挟む習慣をつけておくと、この手のエラーをまとめて防げます。

より短く書きたい場合は、オプショナルチェーン(?.)も使えます。document.getElementById('hamburger')?.addEventListener('click', hamburger);のように書くと、要素がnullのときはaddEventListenerを呼ばずにスキップします。if文を書かずに存在チェックできるので、コードがすっきりします。

なお、要素が実際にはページにあるのにnullになる場合は、スクリプトの読み込み位置が原因のこともあります。要素より前でスクリプトが実行されると、その時点ではまだDOMに存在せずnullになります。その場合は</body>の直前にスクリプトを置くか、DOMContentLoadedの完了を待ってから実行すると解決します。

まとめ

  • 「Cannot read properties of null」は、存在しない要素に対して操作を行ったときのエラー
  • getElementByIdは要素が見つからないとnullを返す
  • 取得した要素をif文でチェックし、存在するときだけaddEventListenerを実行する
  • 全ページ共通のJSでは、要素の存在チェックを習慣にすると安全

よく使うコードほど「動いて当然」と思い込みがちですが、ページの条件が変わると同じコードでもエラーになります。存在チェックのひと手間で、使い回すコードがぐっと堅牢になります。

IPPEI FUKUTA(株式会社バッズブルー 代表)

IPPEI FUKUTA(株式会社バッズブルー 代表)

WordPress専門のWeb制作者として15年・150サイト以上を担当。現場でつまずいた問題と解決策を、同じ制作者・フリーランスの方に向けて発信しています。無料のWeb便利ツール集「バドツール」を開発・運営中。