JavaScript | DOM 操作:CSS / クラス操作 – classList.contains

JavaScript
スポンサーリンク

classList.contains とは何か

classList.contains は、要素に指定した「CSS クラスが付いているか」を真偽値で判定するメソッドです。返り値は true/false のみで、クラス名の完全一致で判断します。ここが重要です:部分一致ではなく“正確なクラス名”に対して安全にチェックできるため、状態分岐やクリック処理の条件判定に最適です。


基本の使い方(状態判定の最短ルート)

付いているかどうかをチェックする

<div id="box" class="card is-active"></div>
<script>
  const box = document.getElementById("box");
  console.log(box.classList.contains("is-active")); // true
  console.log(box.classList.contains("active"));    // false(完全一致ではないため)
</script>
HTML

ここが重要です:contains は「完全一致」だけに反応します。似た名前(active/activated)や部分文字列(light が highlight に含まれる等)では誤判定しません。

判定結果で安全に分岐する

<button id="save" class="btn is-disabled">保存</button>
<script>
  const save = document.getElementById("save");
  if (save.classList.contains("is-disabled")) {
    console.warn("無効なのでクリックを無視");
  } else {
    console.log("保存を実行");
  }
</script>
HTML

ここが重要です:UI の“今の状態”をクラスで表しておけば、contains で直感的に分岐できます。クラスが単一情報源になります。


className.includes との違い(安全性・正確さの深掘り)

文字列検索は危険、contains は厳密

<div id="box" class="card highlight"></div>
<script>
  const box = document.getElementById("box");

  // 悪い例:部分一致の誤判定
  console.log(box.className.includes("light")); // true(highlight に含まれるため誤判定)

  // 正しい例:完全一致
  console.log(box.classList.contains("light")); // false(別クラスとして存在しない)
</script>
HTML

ここが重要です:className.includes は“生の文字列”検索のため、部分一致の罠があります。状態判定には必ず classList.contains を使い、クラス名ははっきり区別できる命名にします。


実践パターン(クリック処理、排他制御、ARIA 連動)

クリックの発生源に応じて処理を分ける

<ul id="menu">
  <li><button class="item">A</button></li>
  <li><button class="item is-disabled">B</button></li>
</ul>
<script>
  const menu = document.getElementById("menu");
  menu.addEventListener("click", (e) => {
    const t = e.target;
    if (!(t instanceof Element)) return;
    const btn = t.closest("button.item");
    if (!btn) return;

    if (btn.classList.contains("is-disabled")) return; // 無効は無視
    console.log("クリック処理を実行");
  });
</script>
HTML

ここが重要です:contains で「対象の状態」を一瞬で判定し、誤動作を防ぎます。イベント委譲と組み合わせて、後から追加された要素にも効きます。

排他的なクラス集合の安全な更新

<div id="toast" class="toast type-info is-hidden"></div>
<script>
  const toast = document.getElementById("toast");
  function show(type) {
    const visible = !toast.classList.contains("is-hidden"); // 今の表示状態
    if (!visible) toast.classList.remove("is-hidden");

    ["type-info", "type-success", "type-error"].forEach(c => {
      if (toast.classList.contains(c)) toast.classList.remove(c);
    });
    toast.classList.add(`type-${type}`);
  }
  show("success");
</script>
HTML

ここが重要です:contains → remove の順で「今付いているものだけを掃除」すれば、不要な操作を減らしつつ、常に正しい集合へ整えられます。

ARIA と連動してアクセシビリティを保つ

<button id="toggle" aria-pressed="false" class="btn"></button>
<script>
  const btn = document.getElementById("toggle");
  btn.addEventListener("click", () => {
    const nowOn = btn.classList.toggle("is-on");
    btn.setAttribute("aria-pressed", String(nowOn));

    // 確認:状態の真偽はクラスで常に取得できる
    if (btn.classList.contains("is-on")) {
      btn.textContent = "ON";
    } else {
      btn.textContent = "OFF";
    }
  });
</script>
HTML

ここが重要です:視覚の状態(クラス)と ARIA の状態を contains の判定で同期すると、見た目とアクセシビリティが噛み合います。


設計のコツ(命名、単一情報源、ヘルパー化)

状態クラスは is-* に統一する

is-active、is-open、is-hidden のような“状態”を示す接頭辞に統一すると、contains の対象が明確になります。ここが重要です:JS は is-* クラスだけを触る契約にすると、テーマ(theme-)や種類(type-)と衝突しません。

単一情報源としてのクラス

表示・挙動・ARIA の判定を同じクラス(例:is-open)に揃えると、contains で一貫して分岐できます。ここが重要です:状態は一箇所で持つ。条件が多いほどこのメリットが効きます。

ヘルパー関数で判定を標準化する

const ACTIVE = "is-active";
function isActive(el) {
  return el.classList.contains(ACTIVE);
}
JavaScript

ここが重要です:クラス名を定数化し、判定を関数に寄せると誤字・曖昧な比較を防げます。大きなコードベースほど効果的です。


よくある落とし穴と回避策(存在・タイミング・曖昧名)

要素が無いときの判定

const el = document.querySelector("#target");
if (!el) return; // null ガード
const on = el.classList.contains("is-on");
JavaScript

ここが重要です:DOM 構築前は null。defer で読み込むか、DOMContentLoaded 後に実行し、常に存在チェックを入れます。

似た名前・部分一致の混乱

active と activated、light と highlight のような似た名前は混乱の元です。ここが重要です:完全一致で判定する前提で、クラス命名をはっきり区別(is-active / is-activated)します。

取得と更新の整合性

contains で見た状態と、次の操作(add/remove/toggle)が一致しないとバグになります。ここが重要です:判定と更新を“同じフレーム”内で行い、外部非同期に影響されないように設計します。


実践例:選択リストのトグルと正確な判定

<ul id="list">
  <li class="item">A</li>
  <li class="item">B</li>
  <li class="item">C</li>
</ul>
<script>
  const list = document.getElementById("list");
  list.addEventListener("click", (e) => {
    const t = e.target;
    if (!(t instanceof Element)) return;
    const li = t.closest(".item");
    if (!li) return;

    const selected = li.classList.contains("is-selected");
    if (selected) {
      li.classList.remove("is-selected"); // 既に選択 → 解除
    } else {
      li.classList.add("is-selected");    // 未選択 → 付与
    }
  });
</script>
HTML

ここが重要です:contains で現状を判定し、add/remove を分ける最も分かりやすい形です。toggle を使ってもよいですが、業務要件で“選択解除時に追加処理をしたい”などの分岐がある場合、contains ベースの明示分岐は読みやすさが勝ります。


まとめ

classList.contains は、要素にクラスが付いているかを「完全一致」で安全に判定するための基本メソッドです。文字列検索の罠(部分一致)を避け、状態分岐・クリック処理・排他制御・ARIA 連動の判断軸として使えます。命名は is-* に統一して単一情報源を作り、定数やヘルパーで判定を標準化する。存在チェックと実行タイミングを守れば、初心者でも意図通りで壊れにくい UI 状態管理が書けます。

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