HTML要素の classList は、「すでに存在するclassを取得するもの」ではありません。
本質的には、その要素の class 属性を、JavaScriptから安全に操作するためのインターフェースです。
たとえば、次のHTMLがあるとします。
<h1 id="target">Hello World</h1>
この要素には class 属性がありません。
しかし、JavaScriptでこう書けます。
const el = document.getElementById("target");
el.classList.add("blue");
これを実行すると、ブラウザ内部では次のような状態になります。
Hello World
つまり、classList.add("blue") は「存在するclassを取得している」のではなく、その要素のclass属性に blue というクラス名を追加しているわけです。
⸻
classList は何を指しているのか
classList は、要素の class 属性を扱うためのオブジェクトです。
el.classList
これは、ざっくり言うと、
この要素のclass属性を操作するための窓口
です。
だから、class 属性が最初から書かれていなくても使えます。
<h1 id="target">Hello World</h1>
この時点では、クラス一覧は空です。
el.classList
は「存在しないからエラー」ではなく、空のクラス一覧として扱われます。
そこに対して、
el.classList.add("blue");
を実行すると、空だったクラス一覧に "blue" が追加されます。
⸻
class 属性はあとから作れる
HTMLでは、属性はあとからJavaScriptで追加できます。
たとえば、最初に class がなくても、
el.setAttribute("class", "blue");
と書けば、class="blue" を付けられます。
つまり、
el.classList.add("blue");
は、よりクラス操作に特化した書き方です。
次の2つは近い意味です。
el.setAttribute("class", "blue");
el.classList.add("blue");
ただし、classList.add() のほうが、複数クラスを安全に扱えます。
⸻
なぜ className ではなく classList があるのか
昔から、要素のclassは className でも操作できます。
el.className = "blue";
これでもclassを付けられます。
ただし、className はclass属性全体を文字列として扱います。
<h1 class="title large">Hello</h1>
この場合、
el.className
は、
"title large"
という文字列です。
つまり、複数のクラスがあっても、ただの文字列として扱われます。
一方で、classList はクラスを1個ずつ扱えます。
el.classList.add("blue");
el.classList.remove("large");
el.classList.toggle("open");
el.classList.contains("title");
このように、「class属性の中身を、スペース区切りの文字列ではなく、クラス名の集合として扱う」ために classList があります。
⸻
classList.add() の本質
el.classList.add("blue");
の本質は、
その要素のclass属性に blue を追加する
です。
最初にclass属性がない場合は、ブラウザが必要に応じて class 属性を作ります。
つまり、次のHTMLが、
<h1 id="target">Hello World</h1>
JavaScript実行後に、
<h1 id="target" class="blue">Hello World</h1>
になる。
これが classList.add() の本質です。
⸻
classList は「取得」ではなく「操作口」
誤解しやすいのは、教材でよく「classListでクラス属性の値を取得する」と説明されることです。
たしかに、
console.log(el.classList);
とすれば、その要素のクラス一覧を見られます。
しかし、実際には classList は取得専用ではありません。
むしろ重要なのは、次のような操作です。
el.classList.add("blue");
el.classList.remove("blue");
el.classList.toggle("blue");
el.classList.contains("blue");
つまり、classList は「classを読むもの」ではなく、class属性を読む・追加する・削除する・切り替えるための操作口です。
⸻
toggle() は何をしているのか
el.classList.toggle("blue");
は、次の処理をまとめたものです。
if (el.classList.contains("blue")) {
el.classList.remove("blue");
} else {
el.classList.add("blue");
}
つまり、
blue があるなら消す
blue がないなら付ける
という処理です。
だから、アコーディオンやメニューの開閉でよく使われます。
button.addEventListener("click", function () {
button.parentElement.classList.toggle("is-open");
});
これは、
クリックされたら、親要素の is-open クラスをON/OFFする
という意味です。
⸻
まとめ
classList は、要素にすでに付いているclassを読むだけのものではありません。
正確には、HTML要素の class 属性をJavaScriptから操作するためのインターフェースです。
そのため、最初に class 属性がない要素に対しても、
el.classList.add("blue");
と書けます。
このとき、ブラウザはその要素に class="blue" を追加します。
つまり、classList の本質は、
class属性を、文字列ではなく、クラス名の一覧として扱う仕組み
です。