ドロワーメニューとは

画面の横から引き出しのようにスライドして出てくるメニュー。開いている間は背景が暗転する。

概要

画面の端(多くは右か左)から、引き出しのようにスライドして出てくるメニューです。 普段はナビゲーションを画面外に隠しておき、ボタンを押したときだけ表示します。 開いている間は背景を暗転させ、背景をクリックしたときやボタンを押したときに閉じるのが一般的な挙動です。

別名

表記ゆれ:ドロワー、オフキャンバスメニュー、ナビゲーションドロワー、サイドメニュー、drawer menu、off-canvas menu

「ドロワー(drawer)」は英語で「引き出し」の意味です。画面の外(キャンバスの外)に一時的にコンテンツを追いやる実装方法であることから「オフキャンバスメニュー」とも呼ばれます。

AI への伝え方

「ドロワーメニューを実装して」で通じます。開く方向(右から/左から)と、閉じる操作(背景クリック・×ボタン・Esc キー)をどこまで用意するかを伝えると仕様がぶれません。

似たパーツとの違い

「ハンバーガーメニュー」は開閉のきっかけになるボタンを指す言葉で、ドロワーメニューはその開いた後の中身(横からスライドして出る実装形式)を指します。 下からスライドして出てくるものは「ボトムシート」、常に画面に表示されたままのものは「サイドバー」と呼び分けます。

デモ

コード

HTML
<div class="drawer-menu-demo">
  <button class="drawer-menu-demo__open" type="button" aria-expanded="false" aria-controls="drawer-menu-demo-panel">
    メニューを開く
  </button>

  <div class="drawer-menu-demo__overlay" id="drawer-menu-demo-overlay" hidden></div>

  <nav class="drawer-menu-demo__panel" id="drawer-menu-demo-panel" aria-label="ドロワーメニュー" hidden>
    <div class="drawer-menu-demo__head">
      <span class="drawer-menu-demo__title">メニュー</span>
      <button class="drawer-menu-demo__close" type="button" aria-label="閉じる">×</button>
    </div>
    <ul class="drawer-menu-demo__list">
      <li><a href="#">トップ</a></li>
      <li><a href="#">サービス</a></li>
      <li><a href="#">会社概要</a></li>
      <li><a href="#">お問い合わせ</a></li>
    </ul>
  </nav>
</div>
CSS
.drawer-menu-demo {
  font-family: sans-serif;
}

.drawer-menu-demo__open {
  padding: 10px 20px;
  border: 0;
  border-radius: 8px;
  background: #0017c1;
  color: #fff;
  font-size: 15px;
  cursor: pointer;
}

.drawer-menu-demo__open:hover {
  background: #00118f;
}

.drawer-menu-demo__overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 100;
}

.drawer-menu-demo__overlay[hidden] {
  display: none;
}

.drawer-menu-demo__panel {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: 260px;
  max-width: 80%;
  background: #fff;
  box-shadow: -4px 0 20px rgba(0, 0, 0, 0.2);
  z-index: 101;
  overflow-y: auto;
}

.drawer-menu-demo__panel[hidden] {
  display: none;
}

.drawer-menu-demo__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px;
  border-bottom: 1px solid #eee;
}

.drawer-menu-demo__title {
  font-weight: bold;
}

.drawer-menu-demo__close {
  border: 0;
  background: transparent;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
  padding: 4px 8px;
}

.drawer-menu-demo__list {
  list-style: none;
  margin: 0;
  padding: 8px;
}

.drawer-menu-demo__list a {
  display: block;
  padding: 10px 12px;
  border-radius: 6px;
  color: #212121;
  text-decoration: none;
}

.drawer-menu-demo__list a:hover {
  background: #f2f2f2;
}
JS
const openButton = document.querySelector(".drawer-menu-demo__open");
const closeButton = document.querySelector(".drawer-menu-demo__close");
const panel = document.getElementById("drawer-menu-demo-panel");
const overlay = document.getElementById("drawer-menu-demo-overlay");

function openDrawer() {
  panel.hidden = false;
  overlay.hidden = false;
  openButton.setAttribute("aria-expanded", "true");
}

function closeDrawer() {
  panel.hidden = true;
  overlay.hidden = true;
  openButton.setAttribute("aria-expanded", "false");
}

openButton.addEventListener("click", openDrawer);
closeButton.addEventListener("click", closeDrawer);
overlay.addEventListener("click", closeDrawer);

document.addEventListener("keydown", (event) => {
  if (event.key === "Escape") closeDrawer();
});