classList は HTML 要素のクラスを安全に操作するための API です。add / remove / toggle / contains / replace のメソッドで、他のクラスに影響を与えずに特定のクラスだけを追加・削除・切り替えできます。
・classList.add() でクラスを追加する方法
・classList.remove() でクラスを削除する方法
・classList.toggle() でクラスを切り替える方法
・classList.contains() でクラスの存在をチェックする方法
・classList.replace() でクラスを置換する方法
・複数クラスの同時操作
・className との違いと使い分け
・ダークモード・タブ・モーダルの実務パターン
classList の全メソッド一覧
| メソッド | 動作 | 戻り値 |
|---|---|---|
| add(cls1, cls2, …) | クラスを追加(既にあれば何もしない) | undefined |
| remove(cls1, cls2, …) | クラスを削除(なければ何もしない) | undefined |
| toggle(cls) | あれば削除、なければ追加 | boolean(追加=true / 削除=false) |
| toggle(cls, force) | force=true で追加、false で削除 | boolean |
| contains(cls) | クラスがあれば true | boolean |
| replace(old, new) | old クラスを new に置換 | boolean(置換できたか) |
| item(index) | N 番目のクラス名を取得 | 文字列 / null |
| length | クラスの数 | 数値 |
| value | 全クラスのスペース区切り文字列 | 文字列(= className と同等) |
add(): クラスを追加する
const el = document.querySelector(".card");
// 1 つ追加
el.classList.add("active");
// 複数同時に追加
el.classList.add("active", "highlight", "animate");
// 既に存在するクラスを追加しても重複しない(エラーにもならない)
el.classList.add("active"); // 2 回目でも問題なし
既にクラスがある状態で add しても重複せず、エラーにもなりません。条件チェックなしで安全に呼び出せます。
remove(): クラスを削除する
// 1 つ削除
el.classList.remove("active");
// 複数同時に削除
el.classList.remove("active", "highlight", "animate");
// 存在しないクラスを削除してもエラーにならない
el.classList.remove("nonexistent"); // 何も起きない
toggle(): クラスを切り替える
// あれば削除、なければ追加
el.classList.toggle("active");
// 1 回目: active がなければ追加 → true を返す
// 2 回目: active があるので削除 → false を返す
// 戻り値で追加/削除を判定
const isNowActive = el.classList.toggle("active");
console.log(isNowActive ? "追加された" : "削除された");
// 第 2 引数(force)で追加/削除を制御
// force=true → 必ず追加(add と同じ)
// force=false → 必ず削除(remove と同じ)
const isLoggedIn = checkLogin();
el.classList.toggle("logged-in", isLoggedIn); // ログイン中なら追加、そうでなければ削除
el.classList.toggle("guest", !isLoggedIn); // ゲストなら追加
// スクロール位置に応じて切り替え
window.addEventListener("scroll", () => {
header.classList.toggle("scrolled", window.scrollY > 100);
});
el.classList.toggle("active", condition) は以下と同じです。if (condition) { el.classList.add("active"); } else { el.classList.remove("active"); }toggle の方が 1 行で書けてシンプルです。
contains(): クラスの存在をチェックする
// クラスがあるか判定
if (el.classList.contains("active")) {
console.log("active クラスがある");
}
// 条件分岐に使う
const isOpen = modal.classList.contains("is-open");
if (isOpen) {
closeModal();
} else {
openModal();
}
replace(): クラスを置換する
// old クラスを new クラスに置換
el.classList.replace("btn-primary", "btn-secondary");
// 戻り値で置換できたか確認
const replaced = el.classList.replace("old", "new");
console.log(replaced); // true(old があれば)/ false(old がなければ)
// テーマの切り替え
function toggleTheme() {
const html = document.documentElement;
if (!html.classList.replace("theme-light", "theme-dark")) {
html.classList.replace("theme-dark", "theme-light");
}
}
classList と className の違い
// className は全クラスを 1 つの文字列として扱う
const el = document.querySelector(".card");
console.log(el.className); // "card active highlight"
// NG: className への代入は全クラスを上書きする
el.className = "new-class";
// → "card" と "active" と "highlight" が全て消えて "new-class" だけになる
// NG: 文字列操作でクラスを追加するのは危険
el.className += " active"; // スペースを忘れると "cardactive" になる
| 項目 | classList | className |
|---|---|---|
| 型 | DOMTokenList(メソッドで操作) | 文字列 |
| 1 つのクラスを追加 | add(“cls”)(他に影響なし) | += ” cls”(スペース忘れのリスク) |
| 1 つのクラスを削除 | remove(“cls”) | 正規表現で置換が必要 |
| クラスの存在チェック | contains(“cls”) | includes(“cls”)(部分一致で誤判定の可能性) |
| 全クラスの上書き | classList.value = “a b c” | className = “a b c” |
| 推奨 | 推奨 | 非推奨(上書きリスク) |
el.className = "active" は元のクラス(card / highlight 等)を全て消して “active” だけにします。classList.add("active") なら他のクラスに影響しません。常に classList を使ってください。複数要素に一括でクラスを操作する
// 全 .card に active を追加
document.querySelectorAll(".card").forEach(card => {
card.classList.add("active");
});
// 全 .tab-btn から active を削除
document.querySelectorAll(".tab-btn").forEach(btn => {
btn.classList.remove("active");
});
// 条件に応じて一括切り替え
const isDark = document.documentElement.classList.contains("dark");
document.querySelectorAll(".icon").forEach(icon => {
icon.classList.toggle("icon-light", isDark);
icon.classList.toggle("icon-dark", !isDark);
});
CSS アニメーションとの連携
.fade-in {
animation: fadeIn 0.3s ease forwards;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
// クラスを追加するだけでアニメーションが発火
el.classList.add("fade-in");
// アニメーション終了後にクラスを削除(再利用のため)
el.addEventListener("animationend", () => {
el.classList.remove("fade-in");
}, { once: true });
JavaScript でスタイルを直接操作するのではなく、CSS でアニメーションを定義し、JavaScript ではクラスの追加/削除だけを行います。CSS と JS の責務が分離され、メンテナブルなコードになります。
要素のクラス一覧を取得・ループする
const el = document.querySelector(".card");
// 全クラスをスペース区切り文字列で取得
console.log(el.classList.value); // "card active highlight"
// className と同じ
console.log(el.className); // "card active highlight"
// クラスの数
console.log(el.classList.length); // 3
// N 番目のクラス
console.log(el.classList.item(0)); // "card"
console.log(el.classList[1]); // "active"(ブラケットでもアクセス可能)
// for...of でループ
for (const cls of el.classList) {
console.log(cls); // "card", "active", "highlight"
}
// 配列に変換
const classArray = [...el.classList];
console.log(classArray); // ["card", "active", "highlight"]
実務パターン集
パターン(1): ダークモードの切り替え
document.querySelector("#theme-toggle").addEventListener("click", () => {
document.documentElement.classList.toggle("dark");
// <html class="dark"> が追加/削除される
// CSS: .dark { --bg: #1a1a2e; --text: #e0e0e0; }
// 設定を保存
const isDark = document.documentElement.classList.contains("dark");
localStorage.setItem("theme", isDark ? "dark" : "light");
});
// ページ読み込み時に保存済みテーマを適用
if (localStorage.getItem("theme") === "dark") {
document.documentElement.classList.add("dark");
}
パターン(2): タブの切り替え
document.querySelectorAll(".tab-btn").forEach(btn => {
btn.addEventListener("click", () => {
// 全タブを非アクティブに
document.querySelectorAll(".tab-btn").forEach(b => b.classList.remove("active"));
document.querySelectorAll(".tab-panel").forEach(p => p.classList.remove("active"));
// クリックされたタブをアクティブに
btn.classList.add("active");
document.querySelector(btn.dataset.target).classList.add("active");
});
});
パターン(3): モーダルの開閉
// 開く
document.querySelector("#open-modal").addEventListener("click", () => {
document.querySelector("#modal").classList.add("is-visible");
document.body.classList.add("modal-open"); // スクロール無効化
});
// 閉じる
document.querySelector("#close-modal").addEventListener("click", () => {
document.querySelector("#modal").classList.remove("is-visible");
document.body.classList.remove("modal-open");
});
パターン(4): スクロール位置でヘッダーのスタイルを変更
window.addEventListener("scroll", () => {
document.querySelector(".header").classList.toggle("scrolled", window.scrollY > 50);
});
// scrollY > 50 なら "scrolled" を追加、それ以下なら削除
パターン(5): 入力バリデーション結果の表示
function validateInput(input) {
const isValid = input.value.length >= 3;
input.classList.toggle("is-valid", isValid);
input.classList.toggle("is-invalid", !isValid);
}
document.querySelector("#name").addEventListener("input", (e) => {
validateInput(e.target);
});
よくある質問
add は冪等(idempotent)で、既にクラスがある場合は何もしません。エラーにもなりません。安心して条件チェックなしで呼び出せます。remove しても何も起きないだけです。contains で事前チェックする必要はありません。toggle はクラスが追加されたら true、削除されたら false を返します。この戻り値を使って追加/削除の結果を判定できます。classList.add("my class")(スペース含む)はエラー(DOMException: InvalidCharacterError)になります。クラス名にスペースを含むことはできません。複数クラスを追加するには add("cls1", "cls2") とカンマ区切りで指定してください。add / remove / toggle / contains は IE 11 で使えます。ただし add("cls1", "cls2")(複数引数)と toggle(cls, force)(第 2 引数)は IE 11 では使えません。IE 対応が必要な場合は 1 つずつ add / remove してください。まとめ
classList の全メソッドをまとめます。
| やりたいこと | 方法 |
|---|---|
| クラスを追加 | el.classList.add(“cls1”, “cls2”) |
| クラスを削除 | el.classList.remove(“cls1”, “cls2”) |
| クラスを切り替え(トグル) | el.classList.toggle(“cls”) |
| 条件付きで追加/削除 | el.classList.toggle(“cls”, condition) |
| クラスの存在チェック | el.classList.contains(“cls”) |
| クラスを置換 | el.classList.replace(“old”, “new”) |
| 全クラスを文字列で取得 | el.classList.value / el.className |
| クラス一覧をループ | for (const cls of el.classList) { … } |
| クラスを配列で取得 | […el.classList] |
クラス名での要素取得は「クラス名で要素を取得する方法」も併せて参照してください。

