背景を1回クリックしたときに、2つのモーダルウィンドウを閉じたいです
最終的にやりたいこと
ハンバーガーメニューアイコンをクリックすると、
チェックボックス1がcheckedになって、
1.親カテゴリーリストを表示するモーダルウィンドウが出現
2.チェックボックス1に連動した画面全体を覆う背景1が出現
↓ 次に
親カテゴリーリストのうちの
任意のカテゴリーをクリックすると、
チェックボックス2がcheckedになって、
1.そのカテゴリーの子カテゴリーリストを表示するモーダルウィンドウが出現
2.チェックボックス2に連動した画面全体を覆う背景2が出現
↓ 最後に
重なる背景1と2を1回クリックしたときに、チェックボックス1とチェックボックス2のcheckedが外れて、
親カテゴリーリストのモーダルウィンドウと子カテゴリーリストのモーダルウィンドウを同時に非表示にしたいです。
実際のサイト https://stalwart-conkies-bbec2c.netlify.app/
ブラウザーの横幅 800px 以下 の場合にハンバーガーメニュー表示するようにしています。
//ハンバーガーメニューアイコン
<label for="a">三</lavel>
//背景1
<label for="a" class="back1"></label>
//背景2
<label for="b" class="back2"></label>
//チェックボックス1
<input type="checkbox" id="a" class="checkbox1">
//チェックボックス2
<input type="checkbox" id="b" class="checkbox2">
//親カテゴリーリスト
<div class="sidebar1">
<ul>
<li>
<label for="b">カテゴリーA</label>
<label for="b">カテゴリーB</label>
<label for="b">カテゴリーC</label>
</li>
</ul>
<div>
//子カテゴリーリスト
<div class="sidebar2">
<ul>
<li>
<label>カテゴリーa1</label>
<label>カテゴリーa2</label>
<label>カテゴリーa3</label>
</li>
</ul>
<div>
//最初は画面外に隠しておく
.sidebar1 {
position: fixed;
z-index: 2;
left: -120%;
}
.sidebar2 {
position: fixed;
z-index: 3;
left: -120%;
}
//チェックボックス1がcheckedになったら、sidebar1を出現させる
.checkbox1:checked ~ .sidebar1 {
left: 0;
}
//チェックボックス1がcheckedになったら、back1を出現させる
.checkbox1:checked ~ .back1 {
position: absolute;
z-index: 1;
top: 0px;
width: 100%;
height: 100%;
background: rgba(154, 144, 144, 0.7);
}
//チェックボックス2がcheckedになったら、sidebar2を出現させる
.checkbox2:checked ~ .sidebar2 {
left: 0;
}
//チェックボックス2がcheckedになったら、back2(透明)を出現させる
.checkbox2:checked ~ .back2 {
position: absolute;
z-index: 1;
top: 0px;
width: 100%;
height: 100%;
background: rgba(154, 144, 144, 0);
}
試したこと
.back1 .back2 ともに
z-index:1
と設定しても、後から、表示させた.back2が上になっているらしく、
1回目のクリックで、
.back2をクリック→チェックボックス2のチェックが外れる→子カテゴリーリストが閉じる
2回目のクリックで、
.back1をクリック→チェックボックス1のチェックが外れる→親カテゴリーリストが閉じる
となってしまい。2回クリックしなければなりません。
他にも、背景を1だけにして、なんとか制御できないかとか考えてみましたが、行き詰まってしまいました。
下記のAmazonのサイトでは、望む動きを実現しています。
https://www.amazon.co.jp/
追記
Next.jsを使って作成しているため、jQueryは使えません。
制約がある中で、UI向上させたいのですが、なにか良い案がありましたら、ご教示いただければ幸いです。
回答者様のアドバイスにより以下のように解決しました。
背景を .back1 の一つだけにしました。
背景とチェックボックスを<label>
のforとidで連動させるのをやめ、
javaScriptで操作するようにしました。
背景とチェックボックスの関係だけでなく、ハンバーガーとチェックボックス、親カテゴリーや子カテゴリーとチェックボックスの関係も、すべて、<label>
連動からjavaScriptに変更しました。
<lavel>とチェックボックス
が、1対1の制御しかできないことの制約に悩まされてきましたが、javaScriptで制御できることで、一気に自由度が高まりました。
修正後のコードは、下記の通りです。
import styles from "../styles/Home.module.css";
import { CategoryData } from "./categorydata";
import { useState } from "react";
const Sidebar = ({ categoryObj, categorySearchItems }) => {
const [secondCategoryData, setSecondCategoryData] = useState([]);
const secondCategorySearchItems = (secondCategoryObj) => {
const checkbox1 = document.getElementById("menu-btn-check1");
const checkbox2 = document.getElementById("menu-btn-check2");
checkbox1.checked = false;
checkbox2.checked = false;
categorySearchItems(secondCategoryObj);
};
const createSecondCategoryData = (firstCategoryObj) => {
if (firstCategoryObj.categoryEArr[0] != "") {
const checkbox1 = document.getElementById("menu-btn-check1");
const checkbox2 = document.getElementById("menu-btn-check2");
console.log("checkbox1c ", checkbox1);
checkbox1.checked = true;
checkbox2.checked = true;
}
console.log("firstCategoryObj", firstCategoryObj);
categorySearchItems(firstCategoryObj);
const categoryObj2 = CategoryData.filter((element) => {
return (
element.categoryEArr[0] == firstCategoryObj.categoryEArr[0] &&
element.categoryEArr.length == 2
);
});
if (typeof categoryObj2 == "undefined") {
setSecondCategoryData({});
} else {
setSecondCategoryData(categoryObj2);
}
};
const toggle = () => {
const checkbox1 = document.getElementById("menu-btn-check1");
if (checkbox1.checked == true) {
checkbox1.checked = false;
} else {
checkbox1.checked = true;
}
};
const disChecked = () => {
const checkbox1 = document.getElementById("menu-btn-check1");
const checkbox2 = document.getElementById("menu-btn-check2");
checkbox1.checked = false;
checkbox2.checked = false;
};
//CategoryDataから要素数1のもの、つまり最上位カテゴリのみのものを抽出
const FirstCategoryData = CategoryData.filter((element) => {
return element.categoryEArr.length == 1;
});
return (
<>
<input
id="menu-btn-check1"
type="checkbox"
className={styles.checkbox1}
/>
{/* <label htmlFor="menu-btn-check1" className={styles.openbtn1}>
<span></span>
<span></span>
<span></span>
</label> */}
<div className={styles.openbtn1} onClick={toggle}>
<span></span>
<span></span>
<span></span>
</div>
{/* <label
htmlFor="menu-btn-check1"
className={styles.back1}
onClick={dischecked}
></label> */}
<div className={styles.back1} onClick={disChecked}></div>
<input
type="checkbox"
id="menu-btn-check2"
className={styles.checkbox2}
/>
{/* <label htmlFor="menu-btn-check2" className={styles.back2}></label> */}
<div className={styles.sidebar1}>
<div className={styles.sidebar1midashi}>カテゴリー</div>
<ul className={styles.sidebar1ul}>
{FirstCategoryData.map((firstCategoryObj, key) => {
return (
<li key={key} className={styles.sidebar1li}>
<div
className={styles.sidebar1label}
id={
categoryObj.categoryEArr[0] ==
firstCategoryObj.categoryEArr[0]
? "active"
: ""
}
onClick={(e) => createSecondCategoryData(firstCategoryObj)}
>
{firstCategoryObj.categoryJArr}
</div>
</li>
);
})}
</ul>
</div>
<div className={styles.sidebar2}>
{/* <label
htmlFor="menu-btn-check2"
className={styles.sidebar2modoru}
onClick={disChecked}
>
← メインメニュー
</label> */}
<div className={styles.sidebar2modoru} onClick={disChecked}>
← メインメニュー
</div>
<div className={styles.sidebar2midashi}>カテゴリー</div>
<div className={styles.sidebar2topCategory}>
{typeof secondCategoryData[0] != "undefined" &&
secondCategoryData[0].categoryJArr[0]}
</div>
<ul className={styles.sidebar2ul}>
{secondCategoryData.map((secondCategoryObj, key) => {
return (
<li key={key} className={styles.sidebar2li}>
<div
className={styles.sidebar2label}
id={
categoryObj.categoryEArr == secondCategoryObj.categoryEArr
? "active"
: ""
}
// onClick={(e) => categorySearchItems(secondCategoryObj)}
onClick={(e) => secondCategorySearchItems(secondCategoryObj)}
>
{secondCategoryObj.categoryJArr[1]}
</div>
</li>
);
})}
</ul>
</div>
</>
);
};
export default Sidebar;
修正後のサイト
https://stalwart-conkies-bbec2c.netlify.app/
サイトの右上に、2つのチェックボックスを表示したままにしておきました。
左がチェックボックス1、右がチェックボックス2です。
ブラウザーの幅800px以下で、ハンバーガーメニューが出現
800px以上の場合は、親カテゴリーリストを最初から表示するようにしています。