※当サイトはアフィリエイト広告を使用しています。
スマホサイトやレスポンシブデザインで定番になっているのが「ハンバーガーボタン」です。
三本線のアイコンを押すとメニューが展開する仕組みで、ナビゲーションをコンパクトにまとめるときによく使われます。
一見シンプルですが、実際に案件で使うには「作り方」や「実装のポイント」を押さえておくことが大切です。
この記事では、普段自分が実務で使っているコードをもとに、ハンバーガーボタンの基本と気をつける点をまとめます。
ハンバーガーボタンとは
ハンバーガーボタンとは、三本線「≡」のアイコンで表現されるナビゲーションボタンのことです。
クリックやタップで隠れていたメニュー(ドロワーメニュー)を表示できる仕組みになっています。
名前の由来は、その形がパンで具材を挟んだハンバーガーに似ていることから。
主にスマートフォンやタブレットなど画面の小さいデバイスで、限られたスペースを有効活用する目的で広く使われています。
メリット
デメリット
現在ではモバイルだけでなく、PCサイトでも使われるケースが増えています。
基本の作り方(HTML / CSS)
まずは完成デモを CodePen で確認してください。
See the Pen Drawer Templete by Suzuki Kazuma (@build_suzuki) on CodePen.
HTMLはシンプルで、button
要素の中に三本の span
を配置します。
<button type="button" class="drawer-button" aria-label="メニューを開閉">
<span class="drawer-button__bar"></span>
<span class="drawer-button__bar"></span>
<span class="drawer-button__bar"></span>
</button>
CSSは、三本線を描くための最低限のスタイルだけ抜粋します。
:root {
--drawer-bar-gap: 8px;
--duration: 300ms;
--easing: ease;
}
.drawer-button {
display: flex;
flex-direction: column;
gap: 4px;
align-items: center;
justify-content: center;
padding: 8px;
background: transparent;
border: none;
cursor: pointer;
}
.drawer-button__bar {
display: block;
width: 32px;
height: 2px;
background-color: #000;
border-radius: 9999px;
transition: transform var(--duration) var(--easing),
opacity var(--duration) var(--easing);
}
.drawer-button__bar:nth-child(1) {
transform: translateY(calc(-1 * var(--drawer-bar-gap)));
}
.drawer-button__bar:nth-child(2) {
transform: translateY(0);
}
.drawer-button__bar:nth-child(3) {
transform: translateY(var(--drawer-bar-gap));
}
これだけで 「三本線のハンバーガーボタン」 を描くことができます。
開閉時の回転やクロスマークへの変化は .is-open
クラスを使って切り替えます。
このコードを使う理由
このハンバーガーボタンのコードは、実案件でそのまま流用できるように設計しています。
とりあえず動けばいいコードではなく、運用や拡張を考えたときに扱いやすい形です。
汎用性が高い
サイズや色、配置はCSS変数やクラスで簡単に調整できます。
新しい案件でも基本部分をそのまま使い回し、デザインに応じて見た目だけ変更可能です。
カスタマイズがしやすい
- ボタンの色は開閉時に変えることができる
- ラベルテキスト(例:「メニュー」)は任意。削除してもエラーは出ない
- 線の太さや間隔はCSSの数値を変えるだけで調整できる
安心して使える設計
button
要素を使っているので、クリックやキーボード操作にも対応- 開閉状態は
.is-open
クラスで一元管理できる - 必要な要素が欠けていてもエラーになりにくいよう配慮
案件ごとに一からコードを書くよりも、ベースを決めておくことで効率的に開発できます。
気をつけたいポイント
どのタグを使うべきか
ハンバーガーボタンは必ず button
要素で実装してください。理由は次のとおり。
- 既定のインタラクションが揃っている
-
button
は標準で「Tabでフォーカス」「Enter/Spaceで押下」「無効化(disabled
)」等が何も書かずに動きます。 - アクセシビリティツリーで“ボタン”として伝わる
-
支援技術(音声読み上げ等)に“ボタン”として正しく認識されます。余計な
role
指定が不要。 - フォームとの衝突を防げる
-
type="button"
を必ず指定(未指定はsubmit
になり得ます)。予期せぬフォーム送信を防止。
推奨の最小マークアップ
<button
type="button"
class="drawer-button"
aria-controls="drawer-nav"
aria-expanded="false"
aria-label="メニューを開閉">
<span class="drawer-button__icon" aria-hidden="true">
<span class="drawer-button__bar"></span>
<span class="drawer-button__bar"></span>
<span class="drawer-button__bar"></span>
</span>
</button>
- ラベルをテキストで出す場合は
aria-label
は省略可。アイコンのみならaria-label
必須。
なぜ div
/ span
はダメなのか
div
や span
は非インタラクティブ要素です。クリックは付けられても、キーボード操作や読み上げの期待値が満たせません。
補強しようとすると実装量と落とし穴が増えます。
典型的NG例(クリックだけ)
<div class="drawer-button">☰</div>
<script>
document.querySelector('.drawer-button').addEventListener('click', toggleMenu);
</script>
改善を試みたが“未完成”な例
<div class="drawer-button" role="button" tabindex="0" aria-label="メニューを開閉"></div>
<script>
const el = document.querySelector('.drawer-button');
el.addEventListener('click', toggleMenu);
el.addEventListener('keydown', (e) => {
// Enter対応はしてるが…
if (e.key === 'Enter') toggleMenu();
// Space対応を忘れがち(Spaceは押下中スクロールも起きやすい)
});
</script>
結局、buttonに戻した方が速くて安全です
どうしても非ボタンで実装するケースでも、role
・tabindex
・Enter/Spaceの両対応・押下時の既定動作抑止など多くの追加対応が要ります。基本は避けましょう。
tabindex
の正しい使い方
tabindex="0"
… フォーカス可能にし、自然な順序に参加(原則:本当に必要な時だけ)。tabindex="-1"
… プログラムでのみフォーカスさせたい時に使用(Tab巡回には入れない)。
- 正の値(例:
tabindex="1"
)はNG … フォーカス順序が壊れます。原則使わない。 - 基本はネイティブ要素(button・aなど)を正しく使うことで
tabindex
すら不要にするのがベスト。
フォーカスが見えるようにする
リセットCSSでアウトラインが消えている場合があります。キーボード操作でフォーカスが見えるのは必須。
/* リセット等で消されている場合に復活 */
.drawer-button:focus { outline: none; } /* マウス時は非表示でもOK */
.drawer-button:focus-visible {
outline: 2px solid #000; /* 目に入る太さ */
outline-offset: 3px;
/* 必要なら box-shadow で代替可 */
}
:focus-visible
はキーボード操作時にだけアウトラインを出す意図に合致。- 背景が暗い/明るいで見え方が変わる場合は、テーマに合わせて色を調整。
視覚的ラベルを非表示にしてアイコンだけにする場合は、スクリーンリーダー向けのテキストを用意すると親切です。
<button type="button" class="drawer-button" aria-controls="drawer-nav" aria-expanded="false">
<span class="sr-only">メニューを開閉</span>
<!-- アイコン -->
</button>
/* 視覚的に隠しつつ読み上げ可能にするユーティリティ */
.sr-only {
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
キーボード操作は実装後に必ず確認
実装後、実機チェックは必須です。自分は以下のような項目を確認しています。
メニューの実装方法については別記事で解説します。
少々お待ちください。
タップ領域とコントラスト
タップ領域は40px四方以上が目安
参考:Material Designのガイド(タッチサイズ)

コントラスト比 4.5:1 以上(本文小サイズ相当の推奨基準)
参考:WCAG 2.1 最低コントラスト(日本語訳 / W3C公式)
参考:Color Contrast Checker
まとめ
ハンバーガーボタンは「三本線を描くだけ」なら簡単ですが、
実際に案件で使うには 押しやすさ・わかりやすさ・操作できること を意識する必要があります。
これらを押さえておけば、どの案件でも安心して使えるハンバーガーボタンになります。
今回の内容を押さえておけば、ほとんどの案件で「背景が動いてしまう」という問題は解決できます。
もっと作り込んだハンバーガーメニューの完成版テンプレートも用意しているので、良かったらあわせてご覧ください。
