JavaScript | DOM 操作:属性操作 – disabled 属性

JavaScript
スポンサーリンク

disabled 属性とは何か

disabled は「フォーム要素を操作不可」にするための“boolean 属性”です。ボタン、入力欄、セレクト、テキストエリア、フィールドセットなどに付けると、フォーカスできず、クリックや入力ができなくなります。ここが重要です:disabled は“値の文字列”ではなく“属性の有無”で判定されます。disabled=”false” と書いても、属性が付いている限り無効のままです。


対象要素と基本挙動(フォーム要素に効く、リンクには効かない)

効く要素の例と基本効果

button、input、select、textarea、fieldset は disabled を付けると操作できなくなり、フォーム送信時も値が送信されません。見た目はユーザーエージェント(ブラウザ)の既定スタイルで“薄く”表示されることが多いです。ここが重要です:disabled の要素はフォーカスも当たらず、Tab ナビゲーションから外れます。

効かない要素と推奨代替

a(リンク)や div などの非フォーム要素には disabled は効きません。リンクを実質無効にしたいなら、aria-disabled=”true” を付け、クリックハンドラで動作を抑止し、Tab でフォーカスさせない設計にします。ここが重要です:意味のある無効化は“アクセシビリティ属性+動作停止”で揃えるのが正解です。


設定と解除(属性の有無で管理するのが正解)

HTML と JavaScript の最小パターン

HTML では <button disabled> のように“存在だけ”を書きます。JavaScript ではプロパティ(el.disabled)か、属性の有無(setAttribute/removeAttribute/toggleAttribute)で管理できます。

<button id="save" disabled>保存</button>
<script>
  const btn = document.getElementById("save");

  // 現在の状態(プロパティで判定)
  console.log(btn.disabled); // true

  // 解除(プロパティ or 属性を外す)
  btn.disabled = false;          // 推奨:読みやすい
  // または
  btn.removeAttribute("disabled");

  // 再度無効化
  btn.disabled = true;
  // または
  btn.toggleAttribute("disabled", true);
</script>
HTML

ここが重要です:boolean 属性は「有無」が真偽。解除は removeAttribute、設定は setAttribute(“”) や toggleAttribute(…, true) が安全ですが、読み書きが最も直感的なのはプロパティ(el.disabled)です。


よくある落とし穴(”false” を入れても有効にならない、送信されない)

“false” という文字列では解除されない

disabled=”false” としても“付いている”ため無効のままです。必ず removeAttribute(“disabled”) または el.disabled = false を使います。ここが重要です:値文字列でコントロールしない。常に“有無”か“プロパティ”で。

フォーム送信に含まれない

disabled が付いた input/select/textarea はフォーム送信時に値が送信されません。読み取り専用にしたいだけなら disabled ではなく readonly(入力不可だが送信はされる)を選びます。ここが重要です:無効化(操作不可+送信しない)と、読み取り専用(操作不可+送信する)の違いを使い分ける。


スタイルとアクセシビリティ(:disabled 擬似クラスと aria の同期)

見た目の統一と操作不可の明示

CSS の :disabled 擬似クラスで統一的な見た目にできます。

button:disabled,
input:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
CSS

ここが重要です:JS で disabled を切り替えれば、擬似クラスが自動で効くため、見た目と挙動が自然に同期します。

aria-disabled の役割

ネイティブに disabled が効かない要素(a など)は aria-disabled=”true” を使い、見た目・読み上げに“操作不可”を伝えます。そのうえでキーボード・クリックを無視するコードを加えます。ここが重要です:視覚(スタイル)・操作(イベント抑止)・読み上げ(ARIA)の3点を揃えると UX が安定します。


フィールドセットの一括無効化(グループで管理)

fieldset に disabled を付けると、内部のフォームコントロールがまとめて無効になります。フォーム全体やセクション単位の制御に便利です。

<fieldset id="group" disabled>
  <input type="text">
  <button>送信</button>
</fieldset>
<script>
  const group = document.getElementById("group");
  group.disabled = false; // 中の要素が一括で有効化
</script>
HTML

ここが重要です:個別に切り替えるより、グループで一括管理するとコードが短く、状態が揃います。


実践例(ロード中の保護、条件妥当性、段階的入力)

ロード中は操作させない

API 呼び出し中に二重クリックを防ぐため、ボタンを一時的に無効化します。

<button id="send" class="btn">送信</button>
<script>
  const send = document.getElementById("send");
  async function submitForm() {
    send.disabled = true;
    try {
      // 非同期処理
      await new Promise(r => setTimeout(r, 800));
    } finally {
      send.disabled = false;
    }
  }
  send.addEventListener("click", submitForm);
</script>
HTML

ここが重要です:try/finally で必ず解除する。失敗時に“無効のまま”を防ぎます。

入力妥当性で有効化する

必須入力が埋まったらボタンを有効にします。

<input id="email" type="email" required>
<button id="next" disabled>次へ</button>
<script>
  const email = document.getElementById("email");
  const next = document.getElementById("next");
  email.addEventListener("input", () => {
    next.disabled = !email.validity.valid;
  });
</script>
HTML

ここが重要です:ブラウザの validity を活用すると、複雑な判定を書かずに済みます。

段階的入力(フィールドセットの切り替え)

ステップが進むまで次のグループを無効にしておき、条件を満たしたら有効化します。

<fieldset id="step1">
  <input id="name" required placeholder="氏名">
</fieldset>
<fieldset id="step2" disabled>
  <input id="addr" required placeholder="住所">
</fieldset>
<button id="go">次へ</button>
<script>
  const step1 = document.getElementById("step1");
  const step2 = document.getElementById("step2");
  const go = document.getElementById("go");
  go.addEventListener("click", () => {
    const name = document.getElementById("name");
    if (name.validity.valid) step2.disabled = false;
  });
</script>
HTML

ここが重要です:段階的に有効化すると、誤入力・誤送信を自然に防げます。


設計の指針(状態の単一情報源と同期)

disabled の真偽を“単一の場所”で決め、他の状態と同期すると保守しやすくなります。クラス(is-loading など)で視覚状態を持ち、disabled はその結果として付け外しします。

function setLoading(btn, on) {
  btn.classList.toggle("is-loading", on);
  btn.disabled = !!on;
  btn.setAttribute("aria-busy", String(!!on));
}
JavaScript

ここが重要です:視覚(クラス)、操作不可(disabled)、読み上げ(ARIA)を一緒に切り替える。状態のズレが起きません。


まとめ

disabled はフォーム要素を“操作不可かつ送信対象外”にする boolean 属性です。真偽は属性の有無で決まり、”false” の文字列では解除できません。設定・解除はプロパティ(el.disabled)か toggleAttribute/removeAttribute を使い、読み取り専用なら readonly を選ぶ。スタイルは :disabled 擬似クラス、アクセシビリティは aria-disabled/aria-busy と同期。fieldset で一括制御すると設計が楽になります。状態の単一情報源を守れば、初心者でも安全でわかりやすい無効化制御が書けます。

タイトルとURLをコピーしました