HTML
この記事では、入力欄やボタンを操作できない状態にし、フォーム送信の対象からも外すdisabled属性の基本と注意点を初心者向けに説明します。
この記事でわかること
disabledがフォーム部品を操作不能にする仕組み- 無効化された値がフォーム送信されないこと
readonly・aria-disabledとの違い
It’s an attribute that completely removes a form control from user interaction and form submission, effectively disabling it.
disabled 属性
- 概要:disabled は何をする属性か
- 基本構文と適用可能要素
- ブラウザ挙動 ── 送信・フォーカス・スタイル
- disabled と readonly の決定的な違い
- CSS :disabled 擬似クラスとスタイリング
- JavaScript での動的制御パターン
- fieldset の一括無効化と例外
- アクセシビリティ & ARIA での拡張
- バリデーション API との関係
- よくある実装シナリオ
- 落とし穴・アンチパターン集
- ブラウザ互換性と仕様の歴史
- 主要フレームワークとの連携 Tips
- ベストプラクティスまとめ
- まとめ
概要:disabled は何をする属性か
- 機能
- フォーム“コントロール”をユーザー操作から 完全に 無効化し、フォーム送信時にも値を送らせない。
- 無効化されたコントロールは、事実上 DOM 上の “装飾” に変わる。
- 仕様位置
- 典型例
- 送信ボタンを条件達成まで押させない、購読プランに応じて入力欄を非活性化。
HTML
<button type="submit" disabled>送信</button>
基本構文と適用可能要素
- 入力系
<input>,<textarea>,<select>- type 不問。テキスト・チェックボックス等すべて
- 選択系
<option>,<optgroup>- 子要素にも波及
- ボタン系
<button>- フォーム部品以外
- 直接は不可。代替は
aria-disabledを使用
静的指定(HTML側)
HTML
<input type="number" name="age" disabled>
動的指定(JS側)
JavaScript
document.querySelector('input[name="age"]').disabled = true;
ブラウザ挙動 ── 送信・フォーカス・スタイル
- 送信時の扱い
- 値は form data に含まれず、
GETクエリやPOST本文に現れない - フォーカス
- キーボード Tab 移動不可。プログラム的
.focus()も無効 - イベント
click/change等の UI イベント発火しない(ただし stop ではなく non-bubble)- UI 表示
- 既定でグレーアウト。
appearanceはブラウザ・OS テーマに依存
disabled と readonly の決定的な違い
| 特性 | disabled | readonly |
|---|---|---|
| 編集 | 不可(そもそも操作不能) | 不可(選択は可) |
| フォーカス | 不可 | 可 |
| 送信 | 値は送信されない | 値は送信される |
| 適用対象 | ほぼ全フォーム要素 | テキスト系のみ (`<input type=text |
CSS :disabled 擬似クラスとスタイリング
CSS
button:disabled,
input:disabled {
opacity: 0.5;
cursor: not-allowed;
}
:enabled と併用して動的テーマを構築可能。
- ブラウザ差異
- Safari は macOS テーマ優先で背景色が上書きできない場合あり。
-
- 回避策
appearance: none;で OS スタイルを外す。
JavaScript での動的制御パターン
フォーム全体を ON/OFF
JavaScript
const form = document.querySelector('form');
form.elements.forEach(el => el.disabled = true);
バリデーションと連動
JavaScript
const btn = document.querySelector('button[type=submit]');
const email = document.querySelector('input[type=email]');
email.addEventListener('input', () => {
btn.disabled = !email.checkValidity();
});
Vue・React 例
HTML
<!-- Vue 3 -->
<button :disabled="!isValid">送信</button>
HTML
<!-- React -->
<button disabled={!isValid}>送信</button>
fieldset の一括無効化と例外
fieldset に disabled を付けると 子孫のすべて が無効化。
- 例外
- 同じ
fieldset内で 最初の<legend>は操作可能。 -
- ラジオボタン切り替え UI などで
legendをクリック可能にしたい場合に配慮。
- ラジオボタン切り替え UI などで
HTML
<fieldset disabled>
<legend>会員情報</legend>
<input name="name">
<input name="email">
</fieldset>
アクセシビリティ & ARIA での拡張
- ネイティブ控えめ
disabled- OS による読み上げ:「利用できません」など自動対応
- カスタム Widget
aria-disabled="true"- JavaScript でキーダウン抑制+フォーカス制御が必要
- 説明ラベル
aria-describedby- 無効理由をスクリーンリーダーに伝える
HTML
<div role="button" aria-disabled="true" tabindex="0" aria-describedby="reason">
Download
</div>
<p id="reason" hidden>契約プランが Basic のため無効です</p>
バリデーション API との関係
disabled要素は Constraint Validation 対象外required,pattern,min/maxなどは無視される。.checkValidity()しても常にtrue。- 送信を制御する 最終手段 として利用可能
- 「そもそも無効にしておけば検証させない」
よくある実装シナリオ
- ステップフォーム
- 現ステップが完了するまで「次へ」ボタンを無効化
- 価格プラン選択
- 無料プランでは高機能入力欄を無効化
- 同意チェックボックス
- 利用規約に同意するまで送信を無効化
- ネットワーク遅延
- 二重送信防止で Ajax 送信中にボタンを一時無効化
落とし穴・アンチパターン集
- ボタンが見た目だけ無効だがクリックできる
disabledではなくclass="disabled"だけ付与- ネイティブ属性を必ず付与
- タブキーで飛ばせない → ユーザー困惑
disabledはフォーカス不可- 非活性でもタブ遷移を維持したい場合は
readonly+aria-disabled - カスタム要素にそのまま
disabledを付与 - 対象外なので無視
- CSS +
aria-disabled+ JS でふるまいを再実装
ブラウザ互換性と仕様の歴史
- 1995年
- HTML 2.0 で初登場(
<input>のみ) - 1997年
- HTML 4.0 で
<button>,<select>等に拡大 - 2019年
- WHATWG HTML で
fieldset・optionの仕様整理 - 現在
- 主要ブラウザは 100% サポート。EdgeHTML 時代のバグ(フォーカス喪失イベント)も解消
- 注意
- 仕様の更新は稀だが アクセシビリティ WG で議論が続くため、非ネイティブ UI では最新の ARIA 実装状況を確認すると安心。
主要フレームワークとの連携 Tips
- React
disabledは真偽値。布値(文字列)を渡すと常にtrue扱いに注意。-
HTML
<button disabled={!canSubmit}>送信</button> - Vue 3
:disabledでバインド。オブジェクトスプレッドで一括制御可。-
HTML
<input v-bind="{ disabled: !canEdit, readonly: canView }"> - Angular
formControlStateで.disable()/.enable()を呼ぶと自動で UI も更新。- Svelte
disabled={condition}。Reactive 宣言と相性◎。
ベストプラクティスまとめ
- 可能な限りネイティブ
disabledを使う - セマンティクス・アクセシビリティが無料で付いてくる
- 視覚的だけでなく動作も無効化する
- CSS だけで “灰色表示” しても意味なし
- ユーザーに理由を示す
aria-describedby+ ツールチップで「なぜ押せないか」説明- 送信直前の非活性化
- 二重送信防止は古典かつ有効
- カスタム UI には
aria-disabled - ボタン以外で「クリック不可」を示すときの必須知識
- 自動テストでは
.disabledor:disabledを assert - 見た目チェックは脆弱
まとめ
disabled 属性は フォーム UX と アクセシビリティ を支える基本要素です。
ネイティブの挙動 を理解し、スタイリング・動的制御・ARIA 代替 を組み合わせれば、初学者でも“触れない”UIを安全に実装でき、上級者は仕様差異まで把握して堅牢なフォームを構築できます。
“無効化” は単なるグレーアウトではなく、相互作用の契約を切る宣言。
その重みを意識してこそ、ユーザーは迷わずフォームを使えるようになります。