質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.32%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

1回答

142閲覧

htmlとjsでモバイル版ハンバーガーメニューを作成したい

try-on-re

総合スコア9

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

0クリップ

投稿2025/03/23 13:12

編集2025/03/23 13:14

実現したいこと

htmlとjsでモバイル版ハンバーガーメニューを作成したい
htmlとcss,jsでサイトを制作しており、レスポンシブやスライド、メニュー制御にjsを使用している。

前提

サイト内htmlそれぞれに対して、【style.js】を経由して画面サイズ判定後【header.html】or【mobiheader.html】とcssを適用する形式でサイトを構築している。
レスポンシブ自体は正常に動作している。
chrome開発者ツールで手動操作を行った内容を統合して【mobimenu.js】を作製したが動作しない。

実現したい動作としては
①メニューボタンをクリック(タップ)すると親メニューが展開
②親メニューをクリックすると子メニューが展開
③メニュー範囲外をクリックするとすべて消える
を実現したいが、動作しない
開発者ツールでクリックイベント登録などをすれば動く

該当のソースコード

【mobimenu.js】
document.addEventListener("DOMContentLoaded", function () {
console.log("✅ DOMContentLoaded が発火しました!");

const menuButton = document.getElementById("menu-button"); const menuContainer = document.getElementById("menu-container"); if (!menuButton || !menuContainer) { console.error("❌ menu-button または menu-container が見つかりません!"); return; } // 大メニューの開閉 menuButton.addEventListener("click", function () { menuContainer.classList.toggle("open"); console.log("📂 menu-container のクラス一覧:", menuContainer.classList); }); // サブメニューの開閉 document.querySelectorAll(".menu-item.has-submenu > a").forEach(item => { item.addEventListener("click", function (event) { event.preventDefault(); event.stopPropagation(); this.parentElement.classList.toggle("open"); console.log("📂 submenu の親要素クラス一覧:", this.parentElement.classList); }); }); // メニュー外をクリックしたら閉じる document.addEventListener("click", function (event) { if (!menuContainer.contains(event.target) && event.target !== menuButton) { menuContainer.classList.remove("open"); document.querySelectorAll(".menu-item.has-submenu").forEach(item => { item.classList.remove("open"); }); console.log("❌ メニューを閉じました!"); } });

});

試したこと

コンソールログの確認や、networkタブの確認で、jsファイルが読み込まれていることは確認している。
① menu-button のイベントを強制リセット&再登録したら、親メニューは開閉するようになった
② 子メニューの click イベントを再登録し、開閉するか確認
③ メニュー外クリックで閉じる処理を再登録し、閉じるか確認
以上を確認してから上記のjsに書き換えたものの、リセットをかけるとまた動かなくなってしまった。


補足情報
使用したいmobiheader.htmlの構造

<html lang="ja"> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>モバイルサイト</title> <link rel="stylesheet" href="css/mobimenu.css"> </head> <body> <div class="main-container"> <div class="header-content"> <header> <div class="banner"> <img src="assets/images/logo.png"
alt="モバイルバナー"> </div> <button id="menu-button" class="menu-button">メニュー</button> <nav id="menu-container" class="menu-container"> <ul class="menu"> <li class="menu-item">ホーム</li> <li class="menu-item has-submenu"> 当社について <ul class="submenu"> <li><a href="gaiyou.html">概要</a></li> <li><a href="about">施設について</a></li> </ul> </li> <li class="menu-item has-submenu"> お知らせ <ul class="submenu"> <li><a href="notice1.html">お知らせ1</a></li> <li><a href="notice2.html">お知らせ2</a></li> </ul> </li> <li class="menu-item has-submenu"> アクセス <ul class="submenu"> <li><a href="map.html">周辺地図</a></li> <li><a href="ac2.html">交通機関</a></li> </ul> </li> </ul> </nav> </header> </div> </div> <script>
<script src="/js/mobimenu.js" defer> </script> </body> </html>

モバイル用のcss【mobistyle.css】
/* 全体のリセット */

  • {
    margin: 0;
    padding: 0;
    box-sizing: border-box;

}
/* 画面幅に応じて、サイドバーを消す */
@media (max-width: 768px) {
.sidebar-left, .sidebar-right, .spacer {
display: none !important;
width: 0 !important;
position: absolute !important;
}
}

/* html と body の高さを100%に設定し、スクロールを防ぐ */
html, body {
height: 100%;
overflow-x: hidden;
display: flex;
flex-direction: column;
}

/* ボディの基本スタイル */
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
color: #333;
}

/* ヘッダー・フッターの初期設定 */
#header-container, #footer-container {
visibility: hidden;
width: 100%;
}

/* メインコンテンツのレイアウト */
.main-container {
flex: 1;
display: flex;
flex-direction: column;
}

.main-content {
flex-grow: 1;
width: 100%;
}

/* スライドショーのスタイル */
.slideshow-container {
position: relative;
width: 100%;
height: auto;
overflow: hidden;
}

.slides {
display: flex;
transition: transform 3s ease-in-out;
}

.slide {
flex: 0 0 100%;
width: 100%;
}

.slides img {
width: 100%;
height: auto;
object-fit: contain;
}

.overlay-image {
position: absolute;
top: 10%;
left: 0;
width: 80%;
pointer-events: none;
}

/* 重要告知ボックス */
.important-message {
background-color: yellow;
padding: 10px;
text-align: center;
font-weight: bold;
color: blue;
transition: opacity 0.3s ease-in-out;
}

.important-message:hover {
opacity: 0.5;
}

/* 最新情報セクション */
.news, .updates {
width: 90%;
margin: 20px auto;
border: 1px solid #ccc;
border-radius: 8px;
overflow: hidden;
padding: 15px;
}

.news-header, .updates-header {
background-color: purple;
color: white;
padding: 10px;
font-size: 1.5em;
text-align: center;
}

.news-content, .updates-content {
background-color: #FFFACD;
color: black;
padding: 15px;
font-size: 1em;
line-height: 1.6;
}

.news-divider, .updates-divider {
width: 90%;
height: 2px;
background-color: red;
margin: 15px auto;
}

.new-label {
color: purple;
font-weight: bold;
}

/* フッターレイアウト */
#footer-container {
position: relative;
width: 100%;
background: #333;
color: white;
text-align: center;
padding: 20px 0;
}

.footer-links {
text-align: center;
margin-bottom: 20px;
}

.footer-links a {
margin: 0 15px;
text-decoration: none;
color: black;
}

.footer-box {
width: 90%;
background-color: yellow;
margin: 0 auto;
padding: 10px;
}

.footer-box p {
color: blue;
font-weight: bold;
}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Lhankor_Mhy

2025/03/24 00:27

ご提示のコードには .menu-item.has-submenu > a がないように見えるのですが、これは問題ありませんか?
try-on-re

2025/03/24 01:49

コメントありがとうございます。 必要な個所には入れていると考えているのですが、具体的にどこに追記が必要そうでしょうか。 追記を試してみたいので、追記すべき場所についてご意見を伺えますと幸いです。
Lhankor_Mhy

2025/03/24 03:36

わかりにくかったようで申し訳ないです。 document.querySelectorAll(".menu-item.has-submenu > a") とスクリプトにありますが、これは、 .menu-item.has-submenu > a というCSSセレクタに当てはまる要素すべて、という意味です。 そして、このセレクタは、 「.menu-itemかつ.has-submenuである要素」の「子要素であるa」 という意味です。 「.menu-itemかつ.has-submenuである要素」に当てはまるのは、 <li class="menu-item has-submenu"> 当社について などですが、その子要素は <ul class="submenu"> だけです。 つまり、 document.querySelectorAll(".menu-item.has-submenu > a") で抜き出せる要素は0個なのですが、これは大丈夫なのでしょうか? 意図している通りの動作ですか? というのが先ほどのコメントの趣旨です。
try-on-re

2025/03/24 06:08

コメントありがとうございます。 ご指摘頂いた内容は今回のエラーとは直接の関係はありませんでしたが、いずれにせよ修正が必要な内容でしたの助かりました。
guest

回答1

0

自己解決

エラーの直接解消ではありませんが、script srcの見直しにより実装したい機能は実現できましたので解決扱いとさせていただきます。
ありがとうございました。

投稿2025/03/24 06:10

try-on-re

総合スコア9

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.32%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問