1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

classがない要素に、なぜ classList.add() できるのか

1
Posted at

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属性を、文字列ではなく、クラス名の一覧として扱う仕組み

です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?