classList.toggle とは何か
classList.toggle は、要素に指定した「CSS クラス」を付けたり外したりするメソッドです。クラスが付いていなければ追加、付いていれば削除します。ここが重要です:第二引数に真偽値を渡すと「常に付ける/常に外す」を明示でき、状態管理が一気に読みやすく、意図通りになります。
基本の使い方(トグルと条件付きトグル)
付いていれば外す、なければ付ける(デフォルト動作)
<button id="btn" class="btn">切り替え</button>
<script>
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
btn.classList.toggle("is-active"); // 付いていれば外す、なければ付ける
});
</script>
HTMLここが重要です:UI の「オン/オフ」操作はこれだけで書けます。複雑な if 文は不要です。
第二引数で「常に付ける/外す」を明示
<div id="panel" class="panel is-hidden"></div>
<button id="open">開く</button>
<button id="close">閉じる</button>
<script>
const panel = document.getElementById("panel");
document.getElementById("open").addEventListener("click", () => {
panel.classList.toggle("is-hidden", false); // 常に外す → 表示
});
document.getElementById("close").addEventListener("click", () => {
panel.classList.toggle("is-hidden", true); // 常に付ける → 非表示
});
</script>
HTMLここが重要です:第二引数は「目標の状態」を表します。true なら付ける、false なら外す。分岐の重複が消え、ミスが減ります。
className や add/remove との使い分け(短く、安全に)
add/remove を一本化できる
function setActive(el, on) {
el.classList.toggle("is-active", !!on);
}
// setActive(el, true) で add、false で remove
JavaScriptここが重要です:同じクラスに対して add/remove を書き分けるより、toggle(, 条件) を一箇所で使うと読みやすく、再利用しやすいです。
className より安全で明確
className は“文字列まるごと”の上書きで、スペースや部分一致の罠があります。toggle は「クラス名の完全一致」を安全に扱い、既存のクラスを壊しません。ここが重要です:部分操作は常に classList 系(add/remove/toggle)が基本。
よく使う UI パターン(開閉、選択、モード切替)
ドロワーの開閉(テキストも連動)
<button id="toggle">開く</button>
<aside id="drawer" class="drawer is-hidden">内容</aside>
<script>
const toggle = document.getElementById("toggle");
const drawer = document.getElementById("drawer");
toggle.addEventListener("click", () => {
const hidden = drawer.classList.toggle("is-hidden");
toggle.textContent = hidden ? "開く" : "閉じる";
});
</script>
HTMLここが重要です:toggle の返り値は「現在の付与状態」(true=付いた、false=外れた)。これを使うと UI 文言を直感的に同期できます。
タブの選択(現在だけ active)
<ul id="tabs">
<li class="tab is-active">A</li>
<li class="tab">B</li>
<li class="tab">C</li>
</ul>
<script>
const tabs = document.getElementById("tabs");
tabs.addEventListener("click", (e) => {
const t = e.target;
if (!(t instanceof Element)) return;
const li = t.closest(".tab");
if (!li) return;
tabs.querySelectorAll(".tab.is-active")
.forEach(el => el.classList.toggle("is-active", false)); // 一括で外す
li.classList.toggle("is-active", true); // 現在だけ付ける
});
</script>
HTMLここが重要です:排他的な状態は「全解除 → 現在だけ付与」で事故が減ります。
ダークモードの切替(状態フラグで制御)
<button id="mode">モード切替</button>
<body class="theme-light"></body>
<script>
const btn = document.getElementById("mode");
btn.addEventListener("click", () => {
const darkNow = document.body.classList.toggle("theme-dark");
document.body.classList.toggle("theme-light", !darkNow);
});
</script>
HTMLここが重要です:互いに排他的なクラスは、片方をトグルし、もう片方を反対値で同期すると常に整います。
命名と設計の深掘り(トグルと相性の良いクラス設計)
is-* を“状態”に限定する
is-active、is-open、is-hidden などの状態クラスは、toggle と相性が最高です。JS は is-* クラスだけを触り、見た目のテーマ(theme-)やタイプ(type-)は別管理にします。ここが重要です:役割を分けると、コードの意図が明確になり、衝突が減ります。
返り値を活用して副作用をまとめる
toggle の返り値(付与後の真偽)で、テキストや aria 属性を一緒に更新します。
const open = panel.classList.toggle("is-open");
button.textContent = open ? "閉じる" : "開く";
button.setAttribute("aria-expanded", String(open));
JavaScriptここが重要です:状態の単一情報源(is-*)から、表示とアクセシビリティを同期すると設計が綺麗です。
よくある落とし穴と回避策(存在・タイミング・排他)
要素存在と実行タイミング
const el = document.querySelector("#target");
if (!el) return; // null ガード
// DOMContentLoaded 以降、または defer スクリプトで実行
JavaScriptここが重要です:DOM がまだ無いと失敗します。存在チェックと実行タイミングを守るのが基本。
相反するクラスの混在
is-hidden と is-open のような“同時に真にしない”クラスが混在すると表示が破綻します。ここが重要です:相反する組はトグル結果で必ず同期(片方を反転値で付け外し)します。
typo と曖昧な名前
toggle は「完全一致」だけが対象。誤字や似た名前(active/activated)を混ぜると効きません。定数で管理するとミスが減ります。
const ACTIVE = "is-active";
el.classList.toggle(ACTIVE, true);
JavaScript実践例:通知バナーの種類と表示状態を切り替える
<div id="toast" class="toast type-info is-hidden">保存しました</div>
<button id="ok">成功</button>
<button id="ng">失敗</button>
<script>
const toast = document.getElementById("toast");
const ok = document.getElementById("ok");
const ng = document.getElementById("ng");
function show(type) {
// 種類を整理(排他的クラスを掃除)
toast.classList.toggle("type-info", type === "info");
toast.classList.toggle("type-success", type === "success");
toast.classList.toggle("type-error", type === "error");
// 表示にする
toast.classList.toggle("is-hidden", false);
}
ok.addEventListener("click", () => show("success"));
ng.addEventListener("click", () => show("error"));
</script>
HTMLここが重要です:toggle(, 条件) で「候補の白リストを一括管理」すると、常に正しいクラス集合に整います。
まとめ
classList.toggle は、クラスを「付ける/外す」を一発で扱えるメソッドです。第二引数で目標状態を明示すれば、add/remove の分岐を一本化でき、排他的クラスの整理も簡潔になります。返り値で UI 文言や aria を同期し、is-* の状態クラスだけを JS で操作する——この設計を徹底すると、初心者でも読みやすく、安全で壊れにくい UI 制御が書けます。
