- JavaScript
JS classListの使い方|add・remove・toggle早見表
classListとは、HTML要素の class 属性を、クラス名1つずつの単位で追加・削除・切り替えできるプロパティです。 要素.classList.add('is-open') のように書くと、すでに付いているほかのクラスはそのままに、指定したクラスだけを操作できます。CSS 側に見た目を書いておき、JavaScript ではクラスの付け外しだけを行う、という役割分担ができるのが大きな利点です。
この記事では、add・remove・toggle・contains・replace を「書き方・戻り値・複数指定の可否」の表にまとめ、toggle の第2引数(強制オンオフ)も実行結果つきで載せました。さらに、メニュー開閉・タブ切り替え・ダークモードの3つを、コピペしてそのまま動く HTML/CSS/JS 一式で用意し、querySelectorAll と forEach での一括切り替え、要素が null のときのエラーの再現と対処まで扱います。掲載した戻り値やエラー文は、すべて Chromium 141.0.7390.37(Playwright 1.56.0 経由)で実際に動かして確かめたものです。Firefox と Safari では実行していません。
classListの早見表
| メソッド | 書き方 | 動き | 戻り値 | 複数指定 |
|---|---|---|---|---|
| add | el.classList.add('a') |
クラスを追加する。すでにあれば何もしない | undefined | できる(add('a', 'b')) |
| remove | el.classList.remove('a') |
クラスを外す。付いていなくてもエラーにならない | undefined | できる(remove('a', 'b')) |
| toggle | el.classList.toggle('a') |
あれば外し、なければ付ける | 真偽値(操作後に付いていれば true) | できない(2つ目は「強制」の指定になる) |
| toggle(第2引数つき) | el.classList.toggle('a', 条件) |
条件が true なら付ける、false なら外す | 真偽値(操作後に付いていれば true) | できない |
| contains | el.classList.contains('a') |
クラスが付いているか調べる | 真偽値 | できない(1つ目だけ調べる) |
| replace | el.classList.replace('old', 'new') |
old を new に置き換える | 真偽値(置き換えたら true、old が無ければ false) | 引数は必ず2つ |
クラス名にはドット(.)を付けません。 querySelector('.card') はセレクタなのでドットが必要ですが、classList のメソッドにはクラス名そのもの('card')を渡します。
プロパティなど、メソッド以外でよく使うものは次のとおりです。
| 書き方 | 内容 | 例(class が "card is-open big" の要素) |
|---|---|---|
el.classList.length |
クラスの数 | 3 |
el.classList[0]、el.classList.item(0) |
指定した位置のクラス名 | 'card' |
el.classList.value |
class 属性の文字列そのもの | 'card is-open big' |
[...el.classList] |
配列に変換 | ['card', 'is-open', 'big'] |
el.classList.forEach((c) => …) |
1つずつ処理 | card、is-open、big の順 |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「JS classListの使い方|add・remove・toggle早見表」
classListの基本
動かして確かめるためのHTML
以降の実行結果は、次の要素に対して順番に操作したものです。
<div id="box" class="card"></div>
<script>
const box = document.querySelector('#box');
console.log(box.classList.add('is-open')); // undefined
console.log(box.className); // "card is-open"
</script>
classNameとの違い
クラスを操作する方法には、昔からある className もあります。className は class 属性を1つの文字列として扱うため、追加や削除のたびに文字列の加工が必要です。
box.className = 'card';
box.className += ' is-open';
console.log(box.className); // "card is-open"
box.className += ' is-open';
console.log(box.className); // "card is-open is-open"(同じクラスが重なる)
box.className = 'note';
console.log(box.className); // "note"(元のクラスが消える)
| 比べる点 | classList | className |
|---|---|---|
| 扱う単位 | クラス名1つずつ | 属性全体の文字列 |
| 追加 | add('a')。重複しない |
+= ' a'。同じ名前が重なる |
| 削除 | remove('a') |
文字列の置換が必要 |
| 有無の確認 | contains('a') |
文字列の検索が必要(部分一致に注意) |
| 全部を入れ替える | el.className = 'x y' のほうが簡単 |
向いている |
| SVG 要素 | そのまま使える | 文字列ではなく SVGAnimatedString というオブジェクトになる |
個別のクラスを付け外しするなら classList、class 属性を丸ごと入れ替えるなら className、という使い分けがわかりやすい基準です。SVG 要素で sv.classList.add('on') が動き、contains('on') が true になることも確かめました。
addでクラスを追加する
box.classList.add('is-open');
console.log(box.className); // "card is-open"
box.classList.add('is-open'); // 同じクラスをもう一度
console.log(box.className); // "card is-open"(重複しない)
すでに付いているクラスを add しても、重複せず、エラーにもなりません。 「付いているか確認してから追加する」という if 文は不要です。
複数のクラスを同時に追加する
box.classList.add('a', 'b', 'c');
console.log(box.className); // "card is-open a b c"
const names = ['s1', 's2'];
box.classList.add(...names); // 配列はスプレッド構文(...)で展開する
引数をカンマで区切って並べます。配列で持っている場合は ... で展開します。空の配列を展開した add(...[]) は、何も追加されずエラーにもなりませんでした。
うまくいかない書き方と直し方
box.classList.add('a b');
InvalidCharacterError: Failed to execute 'add' on 'DOMTokenList': The token provided ('a b') contains HTML space characters, which are not valid in tokens.
| 書き方 | 結果 | 直し方 |
|---|---|---|
add('a b')(空白で区切る) |
InvalidCharacterError で止まる | add('a', 'b') と引数を分ける |
add('')(空文字) |
SyntaxError: … The token provided must not be empty. | 空文字を渡さない。値があるときだけ呼ぶ |
add('.dot')(ドットつき) |
エラーにならず、.dot という名前のクラスが付く |
ドットを外して add('dot') |
add(['m1', 'm2'])(配列をそのまま渡す) |
エラーにならず、m1,m2 という1つのクラスが付く |
add(...['m1', 'm2']) と展開する |
下の2つはエラーが出ないまま意図と違うクラスが付くので、「CSS が効かない」と感じたら、開発者ツールで class 属性の中身を確認してみてください。
removeでクラスを外す
// class="card is-open a b c" の状態から
box.classList.remove('a');
console.log(box.className); // "card is-open b c"
box.classList.remove('b', 'c', 'zzz'); // 複数指定。zzz は付いていない
console.log(box.className); // "card is-open"
付いていないクラスを remove しても、エラーにならず何も起きません。 「必ず閉じた状態にする」といった処理で、気軽に呼べます。
最後のクラスを外したときは、class 属性そのものは空のまま残ります。
box.classList.add('z');
box.classList.remove('z');
console.log(box.outerHTML); // <div id="box" class=""></div>
toggleでクラスを切り替える
toggle は、クラスがあれば外し、なければ付けるメソッドです。ボタンを押すたびに開閉する、といった動きを1行で書けます。
// class="card is-open" の状態から
console.log(box.classList.toggle('is-open')); // false(外れた)
console.log(box.className); // "card"
console.log(box.classList.toggle('is-open')); // true(付いた)
console.log(box.className); // "card is-open"
戻り値は「操作のあとで、そのクラスが付いているかどうか」です。この値を使うと、開閉状態に合わせた処理(ボタンの文言や aria-expanded 属性の更新など)を続けて書けます。
第2引数で強制オン・オフにする
toggle には第2引数(force)があります。true を渡すと「必ず付ける」、false を渡すと「必ず外す」動きになり、切り替えではなく「この状態にする」という指定になります。
// class="card is-open" の状態から
console.log(box.classList.toggle('is-open', true)); // true → "card is-open"(そのまま)
console.log(box.classList.toggle('is-open', false)); // false → "card"
console.log(box.classList.toggle('is-open', false)); // false → "card"(何度呼んでも外れたまま)
| 呼び方 | 動き | 同じ意味の書き方 |
|---|---|---|
toggle('a') |
あれば外す、なければ付ける | if と contains、add、remove の組み合わせ |
toggle('a', true) |
必ず付ける | add('a') |
toggle('a', false) |
必ず外す | remove('a') |
toggle('a', 条件式) |
条件が成り立つときだけ付いた状態にする | if (条件) add('a') else remove('a') |
便利なのは、条件式をそのまま渡せる点です。if 文で add と remove を書き分けていたコードが、1行になります。
// 書き換え前
if (count > 0) {
badge.classList.add('is-visible');
} else {
badge.classList.remove('is-visible');
}
// 書き換え後
badge.classList.toggle('is-visible', count > 0);
第2引数のこの動きは、MDN の DOMTokenList.toggle() のページでも「force を指定すると一方向だけの操作になる。false なら削除のみ、true なら追加のみ」と説明されています(今回このページを開いて確認しました)。
第2引数で気をつけたい点
実際に動かすと、次のような結果になりました。
| 呼び方 | 結果 | 説明 |
|---|---|---|
toggle('p', 'q') |
'p' が付く(何度呼んでも付いたまま)。'q' は付かない | 2つ目の 'q' はクラス名ではなく force として扱われ、空でない文字列なので true 扱い |
toggle('p', 0) |
'p' が外れる | 0 は false 扱い |
toggle('x', undefined) |
通常の切り替えになる(1回目で付き、2回目で外れた) | undefined は「第2引数なし」と同じ |
- toggle では複数のクラスを同時に切り替えられません。 複数を切り替えたいときは、1つずつ呼びます(例:
['a', 'b'].forEach((c) => el.classList.toggle(c)))。 - 第2引数に渡す値が undefined になり得るときは、
Boolean(値)や!!値で真偽値にそろえると、意図しない切り替えを避けられます。たとえばtoggle('is-active', user.isActive)でisActiveが未設定だと、強制オフではなく通常の切り替えになり、クラスが付きました。Boolean(user.isActive)を渡すと外れた状態になります。
containsでクラスの有無を調べる
// class="card" の状態
console.log(box.classList.contains('card')); // true
console.log(box.classList.contains('none')); // false
console.log(box.classList.contains('.card')); // false(ドットは付けない)
if 文の条件として使うのが基本です。
if (menu.classList.contains('is-open')) {
console.log('メニューは開いています');
}
contains は引数を1つだけ見ます。contains('card', 'none') は true、contains('none', 'card') は false でした。複数のクラスをまとめて調べたいときは、配列のメソッドと組み合わせます。
const el = document.querySelector('#box');
// すべて付いているか
const hasAll = ['card', 'is-open'].every((c) => el.classList.contains(c));
// どれか1つでも付いているか
const hasAny = ['card', 'is-open'].some((c) => el.classList.contains(c));
class が "card is-open" の要素では、hasAll と hasAny はどちらも true になりました。セレクタで判定したい場合は el.matches('.card.is-open') という書き方もあり、こちらも true でした。
replaceでクラスを置き換える
// class="card" の状態
console.log(box.classList.replace('card', 'panel')); // true
console.log(box.className); // "panel"
console.log(box.classList.replace('nothing', 'z')); // false(置き換え元が無い)
console.log(box.className); // "panel"(変化なし)
置き換え元のクラスが付いていないときは、何もせず false を返します。 新しいクラスだけが追加されることはありません。「サイズを small から large に変える」「状態を loading から done に変える」のように、どちらか一方だけを付けておきたいときに向いています。
remove と add を続けて書く形との違いは次のとおりです。
| 書き方 | 置き換え元が無いとき |
|---|---|
replace('old', 'new') |
何も起きない(false が返る) |
remove('old'); add('new'); |
new が追加される |
コピペで使える例1:メニュー開閉
ボタンを押すとメニューが開閉する例です。ファイルに保存してブラウザで開けば、そのまま動きます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>メニュー開閉</title>
<style>
.menu { display: none; list-style: none; padding: 8px; border: 1px solid #ccc; }
.menu.is-open { display: block; }
</style>
</head>
<body>
<button id="menuBtn" aria-expanded="false" aria-controls="menu">メニュー</button>
<ul id="menu" class="menu">
<li><a href="#a">お知らせ</a></li>
<li><a href="#b">記事一覧</a></li>
</ul>
<script>
const btn = document.querySelector('#menuBtn');
const menu = document.querySelector('#menu');
btn.addEventListener('click', () => {
// toggle の戻り値(付いたら true)をそのまま aria-expanded に使う
const isOpen = menu.classList.toggle('is-open');
btn.setAttribute('aria-expanded', String(isOpen));
});
// Esc キーで必ず閉じる(remove は付いていなくてもエラーにならない)
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
menu.classList.remove('is-open');
btn.setAttribute('aria-expanded', 'false');
}
});
</script>
</body>
</html>
Chromium で自動操作したときの状態は次のとおりです。
| 操作 | メニューの class | display | aria-expanded |
|---|---|---|---|
| 初期表示 | menu | none | false |
| ボタンを1回クリック | menu is-open | block | true |
| もう1回クリック | menu | none | false |
| 開いた状態で Esc キー | menu | none | false |
| 閉じた状態でさらに Esc キー | menu | none | (エラーなし) |
ポイントは2つです。
- 見た目は CSS、状態の切り替えは classList と役割を分けています。JavaScript は
is-openを付け外しするだけです。 - toggle の戻り値を aria-expanded に反映しています。aria-expanded は、開閉の状態を読み上げソフトなどに伝えるための属性です。
コピペで使える例2:タブ切り替え
選んだタブと、対応するパネルだけに is-active を付ける例です。toggle の第2引数を使うと、「選んだものに付け、それ以外から外す」を1行で書けます。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タブ切り替え</title>
<style>
.tab { padding: 8px 16px; border: 1px solid #ccc; background: #f5f5f5; }
.tab.is-active { background: #1a73e8; color: #fff; }
.panel { display: none; padding: 16px; border: 1px solid #ccc; }
.panel.is-active { display: block; }
</style>
</head>
<body>
<div class="tabs">
<button class="tab is-active" data-target="panel1">概要</button>
<button class="tab" data-target="panel2">仕様</button>
<button class="tab" data-target="panel3">レビュー</button>
</div>
<div id="panel1" class="panel is-active">概要の内容です。</div>
<div id="panel2" class="panel">仕様の内容です。</div>
<div id="panel3" class="panel">レビューの内容です。</div>
<script>
const tabs = document.querySelectorAll('.tab');
const panels = document.querySelectorAll('.panel');
tabs.forEach((tab) => {
tab.addEventListener('click', () => {
// 第2引数が true の要素だけに付き、ほかからは外れる
tabs.forEach((t) => t.classList.toggle('is-active', t === tab));
panels.forEach((p) => p.classList.toggle('is-active', p.id === tab.dataset.target));
});
});
</script>
</body>
</html>
| 操作 | is-active が付いたタブ | 表示されるパネル(display: block) |
|---|---|---|
| 初期表示 | 概要 | panel1 |
| 「仕様」をクリック | 仕様 | panel2 |
| 「レビュー」をクリック | レビュー | panel3 |
| 「レビュー」をもう一度クリック | レビュー(変化なし) | panel3 |
同じタブをもう一度押しても状態が変わらないのは、第2引数つきの toggle が「切り替え」ではなく「この状態にする」動きだからです。第2引数なしの toggle('is-active') で書くと、2回目のクリックで選択が外れてしまいます。
data-target は、タブと対応するパネルの id を結び付けるための独自の属性で、JavaScript からは tab.dataset.target で読み取れます。
コピペで使える例3:ダークモード
body に dark クラスを付け外しして配色を切り替え、選んだ設定を localStorage に保存する例です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ダークモード</title>
<style>
body { background: #ffffff; color: #222222; transition: background .2s, color .2s; }
body.dark { background: #1e1e1e; color: #eeeeee; }
</style>
</head>
<body>
<button id="themeBtn">ダークモードにする</button>
<p>本文のサンプルです。</p>
<script>
const themeBtn = document.querySelector('#themeBtn');
const KEY = 'theme';
// 状態を1か所で反映する関数(force つき toggle で「必ずこの状態にする」)
function applyTheme(isDark) {
document.body.classList.toggle('dark', isDark);
themeBtn.textContent = isDark ? 'ライトモードにする' : 'ダークモードにする';
}
// 初期表示:保存した設定があればそれを、なければ OS の設定を使う
const saved = localStorage.getItem(KEY);
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
applyTheme(saved ? saved === 'dark' : prefersDark);
themeBtn.addEventListener('click', () => {
const isDark = !document.body.classList.contains('dark');
applyTheme(isDark);
localStorage.setItem(KEY, isDark ? 'dark' : 'light');
});
</script>
</body>
</html>
OS の配色設定を「ライト」「ダーク」の両方に切り替えて、Chromium で動かした結果です。
| OS の設定 | 操作 | body の class | 背景色 | ボタンの文言 | 保存された値 |
|---|---|---|---|---|---|
| ライト | 初期表示 | (なし) | rgb(255, 255, 255) | ダークモードにする | なし |
| ライト | クリック | dark | rgb(30, 30, 30) | ライトモードにする | dark |
| ライト | 再読み込み | dark | rgb(30, 30, 30) | ライトモードにする | dark |
| ダーク | 初期表示 | dark | rgb(30, 30, 30) | ライトモードにする | なし |
| ダーク | クリック | (なし) | rgb(255, 255, 255) | ダークモードにする | light |
| ダーク | 再読み込み | (なし) | rgb(255, 255, 255) | ダークモードにする | light |
- 再読み込みしても選んだ配色が保たれることを確認できました。
- 保存した設定がないときは、
prefers-color-scheme(OS の配色設定を調べるメディアクエリ)に合わせています。 applyTheme(isDark)のように、「いまの状態」を引数で受け取って force つき toggle で反映する関数を1つ作っておくと、初期表示とクリック時で同じ処理を使い回せます。
複数の要素をまとめて切り替える(querySelectorAllとforEach)
querySelectorAll() は、条件に合う要素をすべて集めた NodeList を返します。NodeList そのものには classList が無いため、forEach で1つずつ取り出して操作します。
<ul>
<li class="item">A</li>
<li class="item">B</li>
<li class="item">C</li>
</ul>
<script>
// すべての .item に on を付ける
document.querySelectorAll('.item').forEach((el) => el.classList.add('on'));
console.log(document.querySelectorAll('.item.on').length); // 3
// 2番目だけ on にして、ほかは外す
const items = document.querySelectorAll('.item');
items.forEach((el, i) => el.classList.toggle('on', i === 1));
console.log([...items].map((e) => e.className).join(' | ')); // item | item on | item
</script>
条件に合う要素が1つもないとき、forEach は何もせずに終わります。 存在しないクラス .none に対して同じ処理を実行しても、エラーにはなりませんでした。「このページには対象がないかもしれない」という共通スクリプトでも書きやすい形です。
集まりに直接classListを使うとエラーになる
document.querySelectorAll('.item').classList.add('on');
TypeError: Cannot read properties of undefined (reading 'add')
NodeList に classList というプロパティは無いので undefined になり、その add を呼ぼうとしてエラーになります。getElementsByClassName('item').classList.add('on') も同じメッセージでした。
getElementsByClassNameを使うときの注意
| 項目 | querySelectorAll() |
getElementsByClassName() |
|---|---|---|
| 戻り値 | NodeList | HTMLCollection |
| forEach | 使える | 使えない(typeof items.forEach は undefined) |
| for...of | 使える | 使える |
| DOM の変更への追従 | しない(取得時点の一覧) | する(ライブコレクション) |
HTMLCollection は、DOM が変わると中身も自動で変わります。 そのため、取得に使ったクラスをループの中で外すと、処理の途中で一覧が縮みます。
const items = document.getElementsByClassName('item'); // 3つ
let n = 0;
for (const el of items) {
el.classList.remove('item');
n++;
}
console.log('processed ' + n + ' remaining ' + items.length);
processed 2 remaining 1
3つのうち2つしか処理されず、1つ残りました。querySelectorAll('.item') で取得するか、Array.from(items) で配列にしてから処理すると、3つとも処理できます。
要素がnullのときのエラーと対処
classList でいちばんよく出会うエラーが、これです。
document.querySelector('.modal').classList.add('is-open');
TypeError: Cannot read properties of null (reading 'classList')
querySelector() や getElementById() は、要素が見つからないと null を返します。 null には classList が無いので、読み取ろうとした時点でエラーになります。(reading 'classList') と出ていたら、「classList の手前の値、つまり取得した要素が null」と読みます。
原因を切り分ける
| 原因 | 確かめ方 | 直し方 |
|---|---|---|
セレクタのつづり違い、. や # の付け忘れ |
console.log(document.querySelector('…')) が null になる |
セレクタを HTML と照らし合わせる |
| HTML より先にスクリプトが動いている | head 内に script を書いている | DOMContentLoaded を待つ、defer を付ける、body の末尾に置く |
| そのページに要素が存在しない | 共通のスクリプトを複数のページで読み込んでいる | 要素があるときだけ処理する |
| あとから JavaScript で追加される要素 | 取得の時点ではまだ無い | 追加したあとで取得する |
2つ目のケースを再現しました。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<script>
const m = document.querySelector('#menu');
console.log(m);
m.classList.add('is-open');
</script>
</head>
<body>
<ul id="menu"></ul>
</body>
</html>
null
TypeError: Cannot read properties of null (reading 'classList')
head の中のスクリプトは、body の要素が作られる前に実行されます。DOMContentLoaded を待つ形にすると、クラスが付きました。
<script>
document.addEventListener('DOMContentLoaded', () => {
const m = document.querySelector('#menu');
m.classList.add('is-open');
console.log(m.className); // is-open
});
</script>
要素があるときだけ処理する書き方
// 1) if で分岐する
const modal = document.querySelector('.modal');
if (modal) {
modal.classList.add('is-open');
}
// 2) オプショナルチェーン(?.)を使う
document.querySelector('.modal')?.classList.add('is-open');
// 3) querySelectorAll と forEach(0件なら何もしない)
document.querySelectorAll('.modal').forEach((el) => el.classList.add('is-open'));
3つとも、要素が無いページでエラーにならないことを確かめました。?. は、左側が null か undefined のときに、そこで処理をやめて undefined を返す演算子です。
| 書き方 | 向いている場面 |
|---|---|
| if で分岐 | 要素があるときに複数の処理をまとめて行う |
?. |
1行だけの操作を短く書きたい |
| querySelectorAll と forEach | 対象が0個でも複数でも同じコードで扱いたい |
必ず存在するはずの要素には、あえて ?. を付けないという選び方もあります。エラーで止まるほうが、セレクタの書き間違いに早く気づけるためです。
やりたいこと別の逆引き表
| やりたいこと | 書き方 |
|---|---|
| クラスを付ける | el.classList.add('a') |
| 複数のクラスを付ける | el.classList.add('a', 'b') |
| 配列のクラスを付ける | el.classList.add(...names) |
| クラスを外す | el.classList.remove('a') |
| クリックのたびに切り替える | el.classList.toggle('a') |
| 条件に合わせて付け外しする | el.classList.toggle('a', 条件) |
| 付いているか調べる | el.classList.contains('a') |
| 別のクラスに置き換える | el.classList.replace('old', 'new') |
| すべての要素に付ける | document.querySelectorAll('.x').forEach((el) => el.classList.add('a')) |
| 1つだけに付けて、ほかから外す | els.forEach((el) => el.classList.toggle('a', el === target)) |
| クラスをすべて入れ替える | el.className = 'x y' |
| クラスをすべて外す | el.className = '' |
| 要素が無くてもエラーにしない | document.querySelector('.x')?.classList.add('a') |
確認用チェックリスト
- [ ] クラス名にドット(
.)を付けていないか - [ ] 複数のクラスは、空白区切りではなく引数を分けて渡しているか
- [ ] 配列は
...で展開しているか - [ ] toggle に2つ目のクラス名を渡していないか(force として扱われる)
- [ ]
querySelectorAll()の結果に直接 classList を使っていないか - [ ] 要素の取得結果が null になっていないか(
console.logで確認) - [ ] スクリプトは、対象の要素が作られたあとに実行されているか
- [ ] CSS 側に、付け外しするクラスのスタイルを書いてあるか
よくある質問
Q. toggleの戻り値は何ですか?
A. 操作のあとで、そのクラスが付いていれば true、外れていれば false です。const isOpen = menu.classList.toggle('is-open'); のように受け取ると、開閉の状態に合わせた処理を続けて書けます。add と remove の戻り値は undefined でした。
Q. toggleで複数のクラスを同時に切り替えられますか?
A. できません。toggle('p', 'q') と書くと、2つ目の 'q' は「強制的に付ける」という指定として扱われ、p が付いたままになります。複数を切り替えたいときは、['p', 'q'].forEach((c) => el.classList.toggle(c)) のように1つずつ呼びます。
Q. 「Cannot read properties of null (reading 'classList')」と出ます。どこを直せばよいですか?
A. classList の手前で取得した要素が null になっています。セレクタのつづり、スクリプトの実行タイミング(HTML より先に動いていないか)、そのページに要素があるか、の順に確認してください。要素が無いページがあるなら、if か ?. で「あるときだけ処理する」形にします。
Q. classListとstyleは、どちらで見た目を変えるのがよいですか?
A. 基本は classList がおすすめです。見た目を CSS にまとめておけるので、配色やアニメーションをあとから変えるときに JavaScript を触らずに済みます。el.style は、マウスの位置に合わせた座標のように、値をその場で計算して入れる必要があるときに向いています。
まとめ
- classList は、class 属性をクラス名1つずつの単位で操作するプロパティ。ほかのクラスに影響しない
- add と remove は複数指定ができ、戻り値は undefined。重複して付けても、付いていないものを外してもエラーにならない
- toggle は切り替え。戻り値は「操作後に付いているか」の真偽値
- toggle の第2引数に true・false を渡すと、強制オン・オフになる。条件式をそのまま渡せて、タブ切り替えなどが1行で書ける
- contains は有無の確認、replace は置き換え(置き換え元が無ければ false で何もしない)
- 複数の要素は querySelectorAll と forEach で一括操作。集まりに直接 classList は使えない
- 要素が null のときは
Cannot read properties of null (reading 'classList')。if か?.で対処し、取得のタイミングとセレクタを見直す
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「JS classListの使い方|add・remove・toggle早見表」
株式会社RJCでは、JavaScriptでのDOM操作やclassListの使い方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。