フォーム・入力
スイッチ
解説ありSwitch
オン/オフのトグル。チェックボックスとの違いと role="switch" の使い方。
スイッチとは?
スイッチは、オン / オフの2状態をその場で切り替える UI です。 Wi-Fi、通知、ダークモードなど「設定をすぐに反映する」場面で使われます。
チェックボックスと似ていますが、スイッチはその場で即座に反映されるトグル、 という意味合いが強いのが特徴です。どちらを使ってもよい場面も多く、 ネイティブの <input type="checkbox"> でも、role="switch" でも実装できます。
なぜアクセシビリティが大事なの?
「見た目だけのトグル」は、次の人たちに状態が伝わりません。
- キーボード利用者。
<div>ではフォーカスできず、切り替えられません。 - スクリーンリーダー利用者。
role="switch"とaria-checkedが無いと、 「スイッチ」とも「オン/オフ」とも読み上げられず、いまどちらか分かりません。
ポイントは「役割(switch)」と「状態(aria-checked)」を必ずコードで伝えることです。 見た目の色や位置だけで表すのは NG です。
ライブデモ(推奨実装)
下のスイッチは APG に沿った実装です。マウスを使わず、Tab でフォーカスし Enter / Space で切り替えてください。
試してみよう:Tab でフォーカス → Enter でも Space でもオン/オフが切り替わり、状態テキストも連動する。
ポイント
スクリーンリーダーでフォーカスすると「Wi-Fi, スイッチ, オフ」のように読み上げられ、 切り替えると「オン」に変わります。これが role="switch" とaria-checked の効果です(右端の「オフ/オン」テキストは晴眼者向けの補助で、 重複読み上げを避けるため aria-hidden にしています)。
キーボード操作
| キー | 動作 | 必須/任意 |
|---|---|---|
| Tab | 次 / 前のスイッチへフォーカス移動 | 必須 |
| Space | オン / オフを切り替える | 必須 |
| Enter | オン / オフを切り替える | 必須(APGで推奨) |
補足
<button> をベースにすると Enter と Space の両方が自動で効きます。 やることは click ハンドラで aria-checked を反転するだけです。
必要な WAI-ARIA / ロール
| 付ける場所 | 属性 / ロール | 意味 |
|---|---|---|
| スイッチ本体 | <button> + role="switch" | 「スイッチ」として認識させる。ベースが button なのでフォーカス・キー操作が自動。 |
| スイッチ本体 | aria-checked="true | false" | オン / オフの状態。切り替えるたびに必ず更新する。 |
| スイッチ本体 | aria-labelledby または aria-label | 「何の」スイッチかという名前を与える。 |
| 飾りの丸 (thumb) | aria-hidden="true" | 見た目だけの要素を読み上げから除外する。 |
補足
よりシンプルにするなら、ネイティブの <input type="checkbox" role="switch"> と<label> でも実装できます。その場合 aria-checked の管理は不要で、 ブラウザの checked に任せられます。
実装:推奨パターン(Good)
良い例 / 推奨
<button role="switch"> をベースに、aria-checked を状態と同期させます。
マークアップ:
<!-- ラベルとスイッチを横並びにする -->
<span id="wifi-label">Wi-Fi</span>
<button type="button"
role="switch"
aria-checked="false"
aria-labelledby="wifi-label"
id="wifi-switch"
class="switch">
<span class="switch-thumb" aria-hidden="true"></span>
</button>切り替えのスクリプト(aria-checked の更新がすべて):
const sw = document.getElementById('wifi-switch');
if (sw) {
// button なので click(=マウス・Enter・Space)を拾うだけ
sw.addEventListener('click', () => {
const on = sw.getAttribute('aria-checked') === 'true';
// 状態を反転し、aria-checked を必ず更新する
sw.setAttribute('aria-checked', String(!on));
});
}補足
見た目(つまみの位置や色)は aria-checked の値を CSS セレクタ (例:[aria-checked="true"])で切り替えると、状態とスタイルが必ず一致します。 色だけで状態を示さず、形・位置でも区別できるようにしましょう。
アンチパターン(Bad)
下は <div> の見た目を切り替えるだけのトグルです。マウスでは動きますが、キーボードでは触れず、状態も支援技術に伝わりません。
試してみよう:Tab で到達できず、Space でも反応しません。スクリーンリーダーでは『スイッチ』とも『オン/オフ』とも読み上げられません。
<!-- ❌ アンチパターン:見た目だけのトグル -->
<div class="toggle" onclick="this.classList.toggle('on')">
<div class="knob"></div>
</div>悪い例 / 避ける
この実装の問題点:
- キーボードで操作できない —
divはフォーカスを受け取れない。 - 役割が伝わらない —
role="switch"が無く「スイッチ」と認識されない。 - 状態が伝わらない —
aria-checkedが無く、オン/オフが判別できない。 - 名前が無い — 何のスイッチか(Wi-Fi)が関連付けられていない。
ポイント
状態を色だけで示すのも避けましょう(色覚特性のある人に伝わりにくい)。 つまみの位置や ON/OFF のラベルなど、色以外の手がかりも併用します。
実装チェックリスト
- スイッチ本体は
<button>ベース(または<input type="checkbox">) role="switch"が付いている(button ベースの場合)aria-checkedがオン/オフと常に一致しているaria-labelledby/aria-labelで名前を与えている- 飾りのつまみは
aria-hidden="true" - Enter / Space で切り替えられ、フォーカスが見える
- 状態を色だけでなく位置・ラベルでも区別できる