# ドロワーメニューのCSS実装

> ハンバーガーボタンで左からスライドして開くドロワー。transformでの開閉と背景オーバーレイ、aria-expandedの更新を最小のJSで行います。

- カテゴリ: ナビゲーション
- URL: https://www.css-dictionary.com/recipes/drawer-menu/

## HTML

```html
<header class="bar">
  <button type="button" id="menu-btn" class="menu-btn" aria-expanded="false" aria-controls="drawer">
    ☰ メニュー
  </button>
</header>

<div class="backdrop" id="backdrop" hidden></div>

<nav id="drawer" class="drawer" aria-label="メインメニュー">
  <button type="button" id="drawer-close" class="drawer-close" aria-label="メニューを閉じる">×</button>
  <a href="#">ホーム</a>
  <a href="#">プロパティ一覧</a>
  <a href="#">UIレシピ集</a>
</nav>
```

## CSS

```css
.bar {
  padding: 10px;
  background: #fff;
  border: 1px solid #e2d8c2;
  border-radius: 8px;
}

.menu-btn, .drawer-close {
  border: none;
  background: none;
  font: inherit;
  cursor: pointer;
  padding: 6px 10px;
}

.menu-btn:focus-visible, .drawer-close:focus-visible, .drawer a:focus-visible {
  outline: 2px solid #b0413e;
  outline-offset: 2px;
}

.backdrop {
  position: fixed;
  inset: 0;
  background: rgb(26 23 18 / 0.4);
  z-index: 1;
}

.drawer {
  position: fixed;
  inset: 0 auto 0 0; /* 左端に上下いっぱい */
  width: 200px;
  padding: 16px;
  background: #fff;
  border-right: 1px solid #e2d8c2;
  transform: translateX(-100%); /* 初期状態は画面外 */
  transition: transform 0.25s ease;
  z-index: 2;
}

.drawer.is-open {
  transform: none;
}

.drawer a {
  display: block;
  padding: 10px 8px;
  color: #1a1712;
  text-decoration: none;
  border-radius: 6px;
}

.drawer a:hover { background: #f3ecd9; }

.drawer-close {
  display: block;
  margin-left: auto;
  font-size: 18px;
}

@media (prefers-reduced-motion: reduce) {
  .drawer { transition: none; }
}
```

## JavaScript

```js
const menuBtn = document.getElementById('menu-btn');
const drawer = document.getElementById('drawer');
const backdrop = document.getElementById('backdrop');

function setOpen(open) {
  drawer.classList.toggle('is-open', open);
  backdrop.hidden = !open;
  menuBtn.setAttribute('aria-expanded', String(open));
}

menuBtn.addEventListener('click', () => setOpen(true));
document.getElementById('drawer-close').addEventListener('click', () => setOpen(false));
backdrop.addEventListener('click', () => setOpen(false));
```

## 仕組みの解説

ドロワー本体は position: fixed で左端に固定し、初期状態は transform: translateX(-100%) で自分の幅ぶん画面外に置きます。開閉は is-open クラスで transform を切り替えるだけで、transformはレイアウト再計算を起こさないため滑らかです。JSの仕事は「クラスの付け外し・背景の表示・aria-expanded の更新」の3点に絞っています。背景クリックでも閉じられます。

## 実装のポイント

Escキーで閉じる・フォーカスをドロワー内に閉じ込める、まで必要なら<dialog>で作る方が早いです（モーダルダイアログのレシピ参照）。

## AIに依頼するときの文例

左からスライドして開くドロワーメニューを作ってください。transform: translateX(-100%)とクラス切り替えで開閉し、背景オーバーレイのクリックでも閉じ、aria-expandedとaria-controlsを正しく更新する最小のJSを付けてください。

## 使っているプロパティ

- [position](https://www.css-dictionary.com/property/position.md)
- [transform](https://www.css-dictionary.com/property/transform.md)
- [transition](https://www.css-dictionary.com/property/transition.md)
- [inset](https://www.css-dictionary.com/property/inset.md)
- [z-index](https://www.css-dictionary.com/property/z-index.md)

