Element.classList
classListは配列のように扱えるDOMTokenListオブジェクト
// HTML: <div id="main" class="c1 c2 c3"></div> const main = document.getElementById('main'); const classList = main.classList; console.log( classList ); // => DOMTokenList(3) ["c1", "c2", "c3", value: "c1 c2 c3"]
Element.classList.lengthでDOMに付いているクラスの数が返される
main.classList.length; // => 3
配列のようにElement.classList[0]でアクセスするとインデックス番号のクラス名が取得できる
main.classList[0]; // => "c1" // 存在しないインデックスにアクセスすると undefined main.classList[100]; // => undefined
Element.classList.valueはクラス属性の値が文字列で取得できる
main.classList.value; // => "c1 c2 c3" main.classList.value === main.className; // => true
element.classNameで得られる文字列と等しい
classList.value を直接変更するとクラス名が置き換えられる
// HTML: <div id="main" class="c1 c2 c3"></div> const main = getElementById('main'); main.classList.value = "foo bar"; console.log( main.classList ); // => DOMTokenList(2) ["foo", "bar", value: "foo bar"] console.log( main.className ); // => "foo bar" console.log( main ) // => <div id="main" class="foo bar"></div>
同様にclassNameに直接クラス名の値を代入して変更すると、classListの内容変更される
またclassListはオブジェクトなので = で変数に取っておいても元のオブジェクトが変更されると、変数にも変更が反映される反映される
const _classList = main.classList; main.className = "pizza hotdog"; console.log( main.classList ); // => DOMTokenList(2) ["pizza", "hotdog", value: "pizza hotdog"] main.classList === _classList; // => true
method
add( className ): クラスを追加remove( className ): クラスを削除toggle( className ): クラスがあれば削除・無ければ追加contains( className ): クラス名の有無をtrue/falseで返すreplace( oldClass, newClass ): oldClassをnewClassで置き換え
classList.add
add( String [, String [, ...]] )
クラスの追加、,区切りで複数のクラスを一度に追加することもできる
既に存在するクラスは無視される
返り値はundefinedなのでメソッドチェーンはできない
// HTML <div id="main"></div> const main = document.getElementById('main'); main.classList.add('bold'); // => <div id="main" class="bold"></div> main.classList.add('text-info', 'small'); // => <div id="main" class="bold text-info small"></div> console.log( main.classList.add('foo') ); // undefined
,区切りでクラス名を追加できるので、クラス名の配列をスプレッド演算子で展開して渡して追加とかもできる
// HTML <div id="main"></div> const main = document.getElementById('main'); const classArg = ['pizza', 'hotdog', 'gohan']; main.classList.add(...classArg); // => <div id="main" class="pizza hotdog gohan"></div>
classList.remove
remove( String [, String [, ...]] )
クラスの削除、,区切りで複数のクラスを一度に削除もできる
存在しないクラスを削除しようとした場合もエラーにはならない
返り値はundefinedなのでメソッドチェーンはできない
// HTML <div id="main" class="bold text-info small"></div> const main = document.getElementById('main'); main.classList.remove('text-info'); // => <div id="main" class="bold small"></div> main.classList.remove('bold', 'small'); // => <div id="main"></div> main.classList.remove('text-warn'); // => エラーにはならない
classList.contains
contains( String )
クラスが存在しているかどうかをtrue / falseで返す
jQueryで言うところの$elm.hasClass()
// HTML <div id="main" class="error"></div> const main = document.getElementById('main'); main.classList.contains('error'); // => true main.classList.contains('success'); // => false
add, removeのように複数のクラス名を渡してもエラーにはならないが、第一引数以外は無視され第一引数での有無の判定結果が返る
main.classList.contains('error', 'foo'); // => 第一引数の error はあるので true main.classList.contains('foo', 'error'); // => 第一引数の foo はないので false
classList.toggle
toggle( String [, force] )
クラスが存在していれば削除(remove)してfalseを返す・クラスがなければ追加(add)してtrueを返す
第二引数にtrueを渡すと常に追加(add)、falseを渡すと常に削除(remove)
jQueryの$elm.toggleClass(name, switch)と同じ感じ
// HTML: <div id="main"></main> const main = document.getElementById('main'); main.classList.toggle('is_show'); // true // => <div id="main" class="is_show"></main> main.classList.toggle('is_show'); // false // => <div id="main"></main> main.classList.toggle('required', true); // true // => <div id="main" class="required"></main> main.classList.toggle('bold', false); // false // => <div id="main" class="required"></main>
第二引数はforceなので、add, removeのように複数のクラス名をtoggleさせることはできない
// HTML: <div id="main" class="foo"></main> const main = document.getElementById('main'); main.classList.toggle('bar', 'foo'); // => <div id="main" class="foo bar"></main> // * main.classList.toggle('bar', true); と解釈される
スペースが入っているクラス名だとエラーになる
// HTML: <div id="main" class="foo"></main> const main = document.getElementById('main'); main.classList.toggle("foo bar"); // => Error // Uncaught DOMException: Failed to execute 'toggle' on 'DOMTokenList': The token provided ('foo bar') contains HTML space characters, which are not valid in tokens.
\t, \nでも同様にエラーになったが、\s, \d, =, &のようなクラス名としてアレな値が入っていてもエラーにはならなかったので、渡された値がクラス名として成立しているかどうかはチェックしていないっぽい
classList.replace
replace( oldClass, newClass )
第一引数のクラスを、第二引数のクラスに置き換える
置き換えられるoldClassがDOMに無ければ無視される
置き換えるクラス(newClass)が既に存在する場合、置き換えられるoldClassが消えるだけ
// HTML: <div id="main" class="pizza hotdog gohan"></main> const main = document.getElementById('main'); main.classList.replace('gohan', 'beef'); // main.className => "pizza hotdog beef" main.classList.replace('fish', 'chiken'); // main.className => "pizza hotdog beef" main.classList.replace('hotdog', 'pizza'); // main.className => "pizza beef"
classList.toggleと同様にスペースの入っている値を渡すとエラーになる
// HTML: <div id="main" class="pizza beef"></main> const main = document.getElementById('main'); main.classList.replace('pizza beef', 'okome'); // => Error // Uncaught DOMException: Failed to execute 'replace' on 'DOMTokenList': The token provided ('pizza beef') contains HTML space characters, which are not valid in tokens. // 置き換える側も同様 main.classList.replace('pizza', 'okome misosoup'); // => Error // Uncaught DOMException: Failed to execute 'replace' on 'DOMTokenList': The token provided ('okome misosoup') contains HTML space characters, which are not valid in tokens.
正規表現はそもそも受け付けていないのでNG
main.classList.replace(\pizza\, 'misosoup'); // => Error // Uncaught SyntaxError: Invalid or unexpected token
Element.classList - Web API | MDN ここではclassList.replaceはSafari未実装と表示表示されているけど、Can I useではグリーンになっていて、Safari 12.0.3 では問題なく動作していたので使えるっぽい
内部的にclassName.replace(oldClass, newClass)で置き換えているのかと思ったのだけれど、スペースを含むとエラーになるのでどうやら違うっぽい。内部でイテレーター回すとかしてるならclassName.replace()の方が高速な気がする...
// HTML: <div id="main" class="pizza beef"></main> const main = document.getElementById('main'); main.className = main.className.replace('pizza beef', 'okome misosoup'); // => <div id="main" class="okome misosoup"></main>
classList.item
item( index )
引数で渡したインデックスのクラス名を返す
存在しないインデックスを指定するとnullが返る
// HTML: <div id="main" class="pizza hotdog"></div> const main = document.getElementById('main'); console.log( main.classList.item(1) ); // => "hotdog" console.log( main.classList.item(-1) ); // => null
classList[n]で配列ようにアクセスするのとほぼ同じだが、clasList[n] で存在しないインデックスにアクセスした場合undefinedが返るので挙動が異なるので注意が必要
main.classList.item(100) === main.classList[100]; // => false console.log( main.classList.item(100) ); // => null console.log( main.classList[100] ); // => undefined
実装状況

Can I use... Support tables for HTML5, CSS3, etc
IEのサポートをしなくて良いなら問題なく使えそうです
感想
jQueryで行っていたクラス名の操作がほぼ同じ感覚でできるって印象です。(jQuery感覚でメソッドチェーンにするとエラーになりますが...
classList.replaceでのクラス名の置き換えはjQueryだと$elm.add().remove()のように追加・削除をメソッドチェーンしなければならなかったのが単一メソッドで書けるので良いです。
jQueryでの複数クラスの追加・削除はclassNameみたいにスペース区切りの1つの文字列を渡さなければならないので、classListでの操作の方が楽かもしれません。
e. g.
$('#main').addClass('bold text-info'); $('#main').removeClass('bold text-info');
Element.className
const main = document.getElementById('main'); main.className += " bold text-info"; const classArg = main.className.split(' ').filter((val) => { return val !== 'bold' && val !== 'text-info'; }); main.className = classArg.join(' ');
ジャパニランドだとまだまだ使われてる、IEはサポートしてないメソッドも多いので、IEをサポート不要で同じDOMでその後jQueryオブジェクトを使う必然性がなければクラス属性の操作はclassListで事足りそうです。
jQueryとの比較で感想を書いているのは、Vue.jsとかReactのプロジェクトだとクラス名の操作はフレームワークで行うでしょうからclassListの出番はjQuery使ってるwebサイト制作くらいな気がしているから…
[参考]
- Element.classList - Web API | MDN
- element.className - Web API | MDN
- Can I use... Support tables for HTML5, CSS3, etc
- アーティスト: ボレット(ホルヘ),リスト
- 出版社/メーカー: ユニバーサル ミュージック クラシック
- 発売日: 2009/05/20
- メディア: CD
- この商品を含むブログを見る