3秒でわかる
要素の class を「あれば外す、なければ付ける」と一行で反転させる DOM の API。メニュー開閉やダークモード切替を、状態を自分で持たずに書ける。
30秒図解
もう少し詳しく
どういうものか
DOM 要素が持つ classList の中のメソッドで、指定した class 名が付いていれば外し、付いていなければ足します。今の状態を自分で調べる必要がなく、押すたびに反転する動きが一行で書けます。
戻り値は実行後にその class が付いているかどうかの真偽値です。開いた状態かどうかをそのまま受け取れるので、aria-expanded の更新などに使い回せます。第 2 引数に真偽値を渡すと反転をやめ、真なら必ず付ける、偽なら必ず外す動きに変わります。
なぜ必要か
見た目の切り替えを CSS 側に寄せられるからです。JavaScript から style.display を直に書き換えると、色や余白やアニメーションの指定がスクリプトの中に散らばります。class を一つ付け外しするだけにしておけば、どう見えるかは CSS ファイルの中で完結し、変更もそこだけで済みます。
if で分岐して add と remove を呼び分ける書き方に比べ、状態の取り違えが起きにくいのも利点です。現在値を読んでから書くコードは、条件を書き間違えると二度押しで元に戻らなくなります。
具体例
const btn = document.querySelector("#menu-btn");
const nav = document.querySelector("#nav");
// 押すたびに開閉が反転する
btn.addEventListener("click", () => {
const isOpen = nav.<a href="/glossary/classlist" class="text-primary font-medium underline underline-offset-2 hover:text-primary-dark">classList</a>.toggle("open");
btn.setAttribute("aria-expanded", String(isOpen));
});
// 第 2 引数を渡すと反転しない。真なら必ず付き、偽なら必ず外れる
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
document.documentElement.classList.toggle("dark", prefersDark);
// 付け外し以外のメソッド
nav.classList.add("open", "animated");
nav.classList.remove("animated");
console.log(nav.classList.contains("open"));CSS 側は class が付いたときの見た目だけを書きます。
#nav { transform: translateX(-100%); transition: transform .2s; }
#nav.open { transform: translateX(0); }つまずきやすいところ
toggle("open", "animated") と書く。第 2 引数は強制指定なので、"animated" は真として扱われ、常に付いたままになります。複数あるなら一つずつ呼びますtoggle(".open") と書く。セレクタではなく class 名そのものを渡しますclassName に反映させます似た用語との違い
| 書き方 | 動き |
|---|---|
| classList.toggle(name) | 今の状態を見て反転する |
| classList.toggle(name, cond) | 状態を見ずに cond で上書きする |
| classList.add / remove | 常に付ける、常に外す |
| className = "..." | class 属性を丸ごと置き換える。他の class が消える |