ike81818
@ike81818

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

背景を1回クリックしたときに、2つのモーダルウィンドウを閉じたいです

最終的にやりたいこと

ハンバーガーメニューアイコンをクリックすると、

チェックボックス1がcheckedになって、

1.親カテゴリーリストを表示するモーダルウィンドウが出現
2.チェックボックス1に連動した画面全体を覆う背景1が出現

 ↓ 次に

親カテゴリーリストのうちの
任意のカテゴリーをクリックすると、
チェックボックス2がcheckedになって、

1.そのカテゴリーの子カテゴリーリストを表示するモーダルウィンドウが出現
2.チェックボックス2に連動した画面全体を覆う背景2が出現

↓ 最後に

重なる背景1と2を1回クリックしたときに、チェックボックス1とチェックボックス2のcheckedが外れて、
親カテゴリーリストのモーダルウィンドウと子カテゴリーリストのモーダルウィンドウを同時に非表示にしたいです。

###初期画面
スクリーンショット_2022-07-07_11_17_13.png

###親カテゴリーリスト表示時
スクリーンショット_2022-07-07_11_17_27.png

###子カテゴリーリスト表示時
スクリーンショット_2022-07-07_11_17_42.png

実際のサイト https://stalwart-conkies-bbec2c.netlify.app/
ブラウザーの横幅 800px 以下 の場合にハンバーガーメニュー表示するようにしています。

index.html
//ハンバーガーメニューアイコン
<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>

style.css
//最初は画面外に隠しておく
.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で制御できることで、一気に自由度が高まりました。

修正後のコードは、下記の通りです。

components/sidebar.js
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以上の場合は、親カテゴリーリストを最初から表示するようにしています。

0

1Answer

Comments

  1. htmlの埋め込み間違えました。すいません
  2. @ike81818

    Questioner

    ご回答ありがとうございます。
    @murase131さんのおかげで、無事望み通りの挙動を実現できました。
    修正後のコードおよびサイトを投稿に載せておきました。
    心より感謝申し上げます。

Your answer might help someone💌