コピペで完結!ドロワーメニュー #12【複数ドロワーでドロワー内ドロワー】

html/css/js

複数メニューを同時制御/親子メニュー

設定メニューと通知メニューなど、複数のドロワーを同時に扱うサンプルです。親メニューを開いたまま子メニューを操作したり、両方を閉じたりする挙動を制御します。

コードについて 本記事のコードは AI(ChatGPT)による生成をベースに作成・調整しています。ご利用の環境でテストの上ご使用ください。
免責 本コードの利用に伴う不具合・損害について、当サイトは責任を負いません。自己責任にてご利用ください。

デモ

コードをコピーして使おう!

/* =========================================================
   CSS:複数ドロワー(親=設定/子=通知)の同時制御スタイル
   対象スコープ:#multi-drawer-demo の子要素のみ
   目的:
     - 親ドロワーは右端から画面内へスライドイン
     - 子ドロワーは「親を閉じずに」親の右側から重ねて出現
     - オーバーレイは1枚共通、どちらか開いていれば表示
   ========================================================= */

/* 1) ラッパー:位置文脈の起点(将来的な拡張に備えて relative) */
#multi-drawer-demo {
  position: relative; /* 子要素の絶対配置やスタック順調整に備える */
}

/* 2) 共通ボタン(開くボタン) */
#multi-drawer-demo .menu-btn {
  background: #0b6bff;   /* 強調色(青) */
  color: #fff;           /* 白文字でコントラスト確保 */
  border: none;          /* 既定のボーダーを排除 */
  border-radius: 8px;    /* 角丸でタップしやすく */
  padding: 10px 16px;    /* クリック領域確保 */
  cursor: pointer;       /* ポインタカーソル */
  margin: 0 8px 8px 0;   /* ボタン間の余白 */
}

/* 3) オーバーレイ:背景の暗幕(共通1枚) */
#multi-drawer-demo .overlay {
  position: fixed;       /* 画面全体を覆う */
  inset: 0;              /* top/right/bottom/left を一括指定 */
  background: rgba(0,0,0,0.5); /* 半透明の黒で背面を暗くする */
  opacity: 0;            /* 初期は透明(非表示) */
  pointer-events: none;  /* クリック不可(当たり判定なし) */
  transition: .25s;      /* フェードのアニメーション */
  z-index: 90;           /* パネルより背面に配置(数値は親子の間) */
}
/* オーバーレイの有効状態(どちらか開いていれば付与) */
#multi-drawer-demo .overlay.active {
  opacity: 1;            /* フェードイン */
  pointer-events: auto;  /* クリック可能に(タップで閉じる) */
}

/* 4) 親ドロワー(設定):右外→画面内へスライドイン */
#multi-drawer-demo .panel[data-panel="settings"] {
  position: fixed;       /* ビューポート基準に固定表示 */
  top: 0;                /* 上端から始める */
  right: 0;              /* 表示位置は画面右端に固定 */
  height: 100dvh;        /* 端末の動的ビューポート高をフル使用 */
  width: min(80vw, 320px); /* 画面幅に応じて最大320px */
  background: #fff;      /* 本体の背景を白 */
  box-shadow: -6px 0 18px rgba(0,0,0,.25); /* 右からの浮き上がり影 */
  transform: translateX(100%); /* 初期は右の外に隠しておく */
  transition: .3s ease-out;    /* スライドアニメーション */
  z-index: 100;          /* 子より背面(でもオーバーレイより前) */
}
/* 親ドロワーの「開」状態 */
#multi-drawer-demo .panel[data-panel="settings"].active {
  transform: translateX(0); /* 画面内にスライドイン */
}

/* 5) 子ドロワー(通知):親のさらに右側から重ねて出現 */
#multi-drawer-demo .panel[data-panel="notice"] {
  position: fixed;       /* 親とは独立してビューポート基準 */
  top: 0;                /* 上端揃え */
  right: -100%;          /* 初期位置は画面右端のさらに外側 */
  height: 100dvh;        /* 縦全体 */
  width: min(80vw, 300px); /* 親より少し狭めの幅(好みで調整可) */
  background: #fff;      /* 背景白 */
  box-shadow: -6px 0 18px rgba(0,0,0,.25); /* 浮き上がり影 */
  transform: translateX(0); /* 初期は移動せず(rightで位置管理) */
  transition: .3s ease-out; /* スライドアニメーション */
  z-index: 110;          /* 親(100)より前面に表示して重なる */
}
/* 子ドロワーの「開」状態(親の上に重なるように right を 0 に) */
#multi-drawer-demo .panel[data-panel="notice"].active {
  right: 0;              /* 画面右端ピッタリに表示(親の上に重なる) */
  transform: translateX(0); /* ここでは transform は固定のまま */
}

/* 6) 共通のヘッダーと内側配置 */
#multi-drawer-demo .panel header {
  background: #f8fafc;                 /* 薄いグレーで区切り */
  padding: 14px;                        /* 見出しの内側余白 */
  font-weight: 600;                     /* 強調 */
  border-bottom: 1px solid #e5e7eb;     /* 下境界線 */
}
#multi-drawer-demo .panel .inner {
  padding: 16px;                        /* コンテンツの余白 */
}

/* 7) 閉じるボタン:危険色で明確に */
#multi-drawer-demo .close-btn {
  display: block;           /* ブロック化して横幅・余白を扱いやすく */
  margin-top: 20px;         /* 前要素との距離を確保 */
  background: #e11d48;      /* 赤系(注意喚起) */
  color: #fff;              /* 白文字 */
  border: none;             /* 不要な枠を外す */
  border-radius: 6px;       /* 角丸 */
  padding: 8px 12px;        /* クリック領域 */
  cursor: pointer;          /* ポインタ表示 */
}

コメント