【JavaScript】クラス名で要素を取得する方法|querySelectorAll・getElementsByClassName・classList・複数クラス・実務パターンまで解説

【JavaScript】クラス名で要素を取得する方法|querySelectorAll・getElementsByClassName・classList・複数クラス・実務パターンまで解説 JavaScript

JavaScript で特定のクラス名を持つ HTML 要素を取得するには、querySelectorAll または getElementsByClassName を使います。取得した要素に対してスタイルの変更、イベントの登録、表示の切り替えなど様々な操作が可能です。

本記事では、2 つの取得方法の違い複数クラスでの絞り込みループ処理classList でのクラス操作まで解説します。

この記事でわかること
・querySelectorAll / querySelector でクラス名から要素を取得する方法
・getElementsByClassName との違い(静的 vs ライブコレクション)
・複数クラスの AND / OR 条件で絞り込む方法
・取得した要素をループで処理する方法
・classList で要素のクラスを追加・削除・切り替え
・closest() で最も近い親要素を検索する方法
・タブ切り替え・アコーディオン等の実務パターン
スポンサーリンク

querySelectorAll / querySelector(推奨)

HTML(サンプル)
<div class="card active">カード1</div>
<div class="card">カード2</div>
<div class="card active">カード3</div>
<div class="item">アイテム</div>
JavaScript(querySelectorAll: 全要素を取得)
// .card クラスを持つ全要素を取得
const cards = document.querySelectorAll(".card");
console.log(cards.length); // 3

// .card.active の両方を持つ要素(AND 条件)
const activeCards = document.querySelectorAll(".card.active");
console.log(activeCards.length); // 2

// .card または .item(OR 条件: カンマ区切り)
const mixed = document.querySelectorAll(".card, .item");
console.log(mixed.length); // 4
JavaScript(querySelector: 最初の 1 要素だけ取得)
// 最初の .card 要素だけ取得
const firstCard = document.querySelector(".card");
console.log(firstCard.textContent); // "カード1"

// 見つからない場合は null
const notFound = document.querySelector(".nonexistent");
console.log(notFound); // null
querySelector / querySelectorAll が推奨
CSS セレクタ構文をそのまま使えるため、クラス名・ID・属性・疑似クラスなどあらゆる条件で検索できます。getElementsByClassName より柔軟で統一的に使えるため、現在の開発では querySelector 系を標準的に使います

getElementsByClassName

JavaScript(getElementsByClassName)
// クラス名で要素を取得(ドット不要)
const cards = document.getElementsByClassName("card");
console.log(cards.length); // 3

// 複数クラスの AND 条件(スペース区切り)
const activeCards = document.getElementsByClassName("card active");
console.log(activeCards.length); // 2

querySelectorAll と getElementsByClassName の違い

項目 querySelectorAll getElementsByClassName
セレクタ構文 CSS セレクタ(.class / #id / [attr] 等) クラス名のみ
クラス名の指定 ドットが必要(”.card”) ドット不要(”card”)
戻り値 NodeList(静的: 取得時点のスナップショット) HTMLCollection(ライブ: DOM の変化が反映)
forEach 使える 使えない(Array.from で変換が必要)
OR 条件 “.card, .item”(カンマ区切り) 不可
推奨 推奨 後方互換。新規コードでは querySelector を推奨
ライブコレクション(HTMLCollection)の罠
getElementsByClassName が返す HTMLCollection はライブです。ループ中に要素のクラスを変更すると、コレクションの中身がリアルタイムで変わり、意図しないスキップや無限ループの原因になります。querySelectorAll(静的 NodeList)を使えばこの問題は起きません。
JavaScript(ライブコレクションの罠)
// NG: ライブコレクションでループ中にクラスを変更
const items = document.getElementsByClassName("old");
for (let i = 0; i < items.length; i++) {
  items[i].classList.replace("old", "new");
  // クラスが変わると items から消える → 次の要素がスキップされる!
}

// OK: querySelectorAll なら安全
const items2 = document.querySelectorAll(".old");
items2.forEach(el => {
  el.classList.replace("old", "new"); // 安全(静的コレクション)
});

取得した要素をループで処理する

JavaScript(ループの書き方)
// forEach(最もシンプル: NodeList で使用可能)
document.querySelectorAll(".card").forEach(card => {
  card.style.border = "1px solid blue";
});

// for...of
for (const card of document.querySelectorAll(".card")) {
  card.style.border = "1px solid blue";
}

// 通常の for ループ(インデックスが必要な場合)
const cards = document.querySelectorAll(".card");
for (let i = 0; i < cards.length; i++) {
  cards[i].style.border = "1px solid blue";
}

// getElementsByClassName を forEach で使う場合
const collection = document.getElementsByClassName("card");
Array.from(collection).forEach(card => {
  card.style.border = "1px solid blue";
});
ループ方法 NodeList HTMLCollection 推奨度
forEach 直接使用可 Array.from() が必要 高(シンプル)
for…of 使用可 使用可
for (i) 使用可 使用可 中(インデックスが必要な場合)
[…spread] 使用可 使用可 高(配列メソッドと組み合わせ)

classList でクラスを操作する

JavaScript(classList のメソッド)
const el = document.querySelector(".card");

// クラスの追加
el.classList.add("active");
el.classList.add("highlight", "animate"); // 複数同時追加

// クラスの削除
el.classList.remove("active");

// クラスの切り替え(あれば削除、なければ追加)
el.classList.toggle("active");

// 条件付き切り替え(true=追加 / false=削除)
el.classList.toggle("active", isLoggedIn);

// クラスの存在チェック
if (el.classList.contains("active")) {
  console.log("active クラスがある");
}

// クラスの置換
el.classList.replace("old-class", "new-class");
メソッド 動作
add(cls) クラスを追加(既にあれば何もしない)
remove(cls) クラスを削除(なければ何もしない)
toggle(cls) あれば削除、なければ追加
toggle(cls, force) force=true で追加、false で削除
contains(cls) クラスがあれば true
replace(old, new) クラスを置換
className の直接代入は避ける
el.className = "new-class" は既存のクラスを全て上書きします。classList.add() / classList.remove() なら他のクラスに影響せず安全にクラスを操作できます。

特定の親要素内から検索する

JavaScript(スコープを絞った検索)
// 特定の親要素内からのみ検索
const sidebar = document.querySelector(".sidebar");
const sidebarLinks = sidebar.querySelectorAll(".nav-link");
// .sidebar 内の .nav-link だけ取得(ページ全体は検索しない)

// CSS 子孫セレクタと同等
const headerLinks = document.querySelectorAll(".header .nav-link");

closest() で最も近い祖先要素を検索する

JavaScript(closest: 自分自身を含む最も近い祖先)
// クリックされた要素から最も近い .card を探す
document.addEventListener("click", (e) => {
  const card = e.target.closest(".card");
  if (card) {
    console.log("カードがクリックされた:", card.textContent);
  }
});

// イベントデリゲーションとの組み合わせ
document.querySelector(".card-list").addEventListener("click", (e) => {
  const deleteBtn = e.target.closest(".delete-btn");
  if (deleteBtn) {
    const card = deleteBtn.closest(".card");
    card.remove();
  }
});
closest() はイベントデリゲーションの必須テクニック
子要素がクリックされたときに親要素(.card)を特定するのに使います。closest() は自分自身を含む祖先を上方向に検索し、一致する最初の要素を返します。見つからない場合は null を返します。

matches() で要素がセレクタに一致するかチェック

JavaScript(matches)
const el = document.querySelector(".card");

// 要素が特定のセレクタに一致するか
console.log(el.matches(".card"));         // true
console.log(el.matches(".card.active"));  // true / false
console.log(el.matches(".item"));         // false

// イベントハンドラ内で使う
document.addEventListener("click", (e) => {
  if (e.target.matches(".delete-btn")) {
    handleDelete(e.target);
  }
});

実務パターン集

パターン(1): タブ切り替え

JavaScript
document.querySelectorAll(".tab-btn").forEach(btn => {
  btn.addEventListener("click", () => {
    // 全タブの active を解除
    document.querySelectorAll(".tab-btn").forEach(b => b.classList.remove("active"));
    document.querySelectorAll(".tab-content").forEach(c => c.classList.remove("active"));

    // クリックされたタブと対応コンテンツに active を付与
    btn.classList.add("active");
    const target = document.querySelector(btn.dataset.target);
    if (target) target.classList.add("active");
  });
});

パターン(2): 全要素の表示/非表示切り替え

JavaScript
// .notification クラスの全要素を非表示にする
function hideAll(className) {
  document.querySelectorAll(`.${className}`).forEach(el => {
    el.style.display = "none";
  });
}

// .notification クラスの全要素を表示する
function showAll(className) {
  document.querySelectorAll(`.${className}`).forEach(el => {
    el.style.display = "";
  });
}

パターン(3): 条件に合う要素だけフィルタ

JavaScript
// data-category 属性で絞り込み
function filterByCategory(category) {
  document.querySelectorAll(".product").forEach(product => {
    if (category === "all" || product.dataset.category === category) {
      product.style.display = "";
    } else {
      product.style.display = "none";
    }
  });
}

パターン(4): 配列メソッドとの組み合わせ

JavaScript
// NodeList を配列に変換して filter / map を使う
const activeItems = [...document.querySelectorAll(".item")]
  .filter(el => el.classList.contains("active"))
  .map(el => el.textContent);

console.log(activeItems); // ["アイテム1", "アイテム3"]

よくある質問

QquerySelectorAll と getElementsByClassName はどちらを使うべきですか?
AquerySelectorAll を推奨します。CSS セレクタをそのまま使えて柔軟性が高く、返される NodeList が静的なのでループ中のクラス変更も安全です。getElementsByClassName は後方互換のためにまだ使えますが、新規コードでは querySelector 系に統一するのがベストです。
QquerySelectorAll の戻り値に forEach が使えません
AquerySelectorAll の NodeList は forEach に対応しています(IE 11 以外)。getElementsByClassName の HTMLCollection は forEach に対応していないため、Array.from(collection).forEach(...) で変換してください。
Qクラス名の先頭のドット(.)を忘れてエラーになります
AquerySelectorAll は CSS セレクタ構文なのでドット(.)が必須です。getElementsByClassName はクラス名だけを渡すのでドット不要です。
querySelectorAll(".card") / getElementsByClassName("card")
Q要素が見つからない場合はどうなりますか?
AquerySelectornull を返します。querySelectorAll は空の NodeList(length=0)を返します。null チェックを忘れると TypeError: Cannot read properties of null が発生するため、if (el) { ... } で確認してください。
Qclosest() は IE で使えますか?
AIE 11 では closest()使えません。ポリフィルを使うか、ループで parentElement を辿る方法で代替できます。ただし IE は 2022 年にサポート終了しているため、現在の開発では考慮不要なケースがほとんどです。
Q動的に追加された要素にもイベントを付けたいです
AquerySelectorAll は実行時点の要素しか取得できません。後から追加される要素にも対応するにはイベントデリゲーションを使います。親要素にイベントを登録し、e.target.closest(".target-class") で対象を判定してください。

まとめ

クラス名による要素取得の要点をまとめます。

やりたいこと 方法
クラスで全要素を取得(推奨) document.querySelectorAll(“.class-name”)
クラスで最初の 1 要素を取得 document.querySelector(“.class-name”)
複数クラスの AND 条件 querySelectorAll(“.class1.class2”)
複数クラスの OR 条件 querySelectorAll(“.class1, .class2”)
親要素内から検索 parent.querySelectorAll(“.class-name”)
最も近い祖先要素を検索 element.closest(“.class-name”)
クラスの追加 element.classList.add(“class-name”)
クラスの削除 element.classList.remove(“class-name”)
クラスの切り替え element.classList.toggle(“class-name”)
クラスの存在チェック element.classList.contains(“class-name”)