つくる ダークモード切替
このレッスンで分かること
classList.toggleは、付いていれば外し、無ければ付けますtoggleの戻り値は実行後に付いているかどうかで、ボタンの文言の切り替えにそのまま使えます
1 回目は変わるのに、2 回目が戻らない
押したら見た目が変わるボタンを作るとき、多くの人が最初にこう書きます。
JavaScript
menuButton.addEventListener("click", function () {
menu.classList.add("is-open");
});1 回目はちゃんと開きます。ところが、もう一度押しても閉じません。add はすでに付いていれば黙って何もしないからです。切り替えは往復して初めて切り替えです。
今回作るのはダークモードの切り替えボタンです。決まりは次のとおりです。
- ヘッダーの
navのうしろにid="theme-toggle"class="theme-toggle"type="button"のボタンを足し、文字は「ダークモード」にする - そのボタンに
clickを登録し、document.bodyの class を切り替える - 切り替えた結果を受け取って、ボタンの文字を「ライトモード」と「ダークモード」で入れ替える
見た目の CSS は用意してあります。書けたら必ず 2 回押して、明るい状態まで戻ることを確かめてください。
toggle なら 1 行で済む
add と remove を自分で振り分けても書けます。
JavaScript
if (menu.classList.contains("is-open")) {
menu.classList.remove("is-open");
} else {
menu.classList.add("is-open");
}間違ってはいませんが、これとまったく同じことが menu.classList.toggle("is-open") の 1 行で書けます。条件分岐が消えるぶん、読み違いも起きません。切り替えを書くときは toggle を第一候補にしてください。
| メソッド | 動き | 戻り値 |
|---|---|---|
| add | 付ける。すでにあれば何もしない | なし |
| remove | 外す。無ければ何もしない | なし |
| toggle | あれば外し、無ければ付ける | 実行後に付いているか |
| contains | 付いているかを調べる | true か false |
toggle は実行後の状態を真偽値で返します。付いた直後なら true、外れた直後なら false です。この戻り値をそのまま使えば、contains で調べ直さずにボタンの文字もそろえられます。
JavaScript
const opened = menu.classList.toggle("is-open");
menuButton.textContent = opened ? "メニューを閉じる" : "メニューを開く";第3章の三項演算子が短く効いています。ボタンの文言を「いまの状態」にするか「押したらどうなるか」にするかは設計の分かれ目ですが、行き先を書くほうが押す前に迷いません。
色は CSS に、名前の付け外しは JavaScript に
配色を切り替えるとき、style.backgroundColor に色を代入していく書き方でも動きます。ただし色の数だけ行が増え、どこで何色にしたのか追えなくなります。JavaScript がやるのは class を付け外しすることだけにして、その class が付いたときの見た目は CSS に書きます。
CSS
body.dark {
background-color: #1b1f27;
color: #e8eaee;
}
body.dark .section {
background-color: #242a34;
}class を付ける相手は、変えたい範囲のいちばん外側にします。ページ全体の配色を変えたいなら document.body です。.section それぞれに付けて回ると、要素の数だけ処理が増えるうえ、あとから足した要素には付きません。外側 1 か所に付けて、中は CSS の子孫セレクタで受ける。これなら JavaScript は 1 行のままです。
現場では is-open is-active is-loading has-error のように、状態を表す class に is- や has- を付ける習慣があります。形を決める class と読み分けられるようにするためです。
よくある間違い
- class 名にドットを付ける —
classListに渡すのは class 名そのものです。ドットが要るのはquerySelectorのセレクタのときだけで、.darkという名前の class が付いてしまい CSS には当たりません classNameを上書きする —document.body.className = "dark"は class 全体を置き換える書き方です。元から付いていた class が消えます。付け外しにはclassListを使います
課題
- HTML の
.site-headerの中、navのうしろにid="theme-toggle"class="theme-toggle"type="button"のボタンを足し、文字は「ダークモード」にする - JavaScript で
#theme-toggleにclickを登録する - 処理の中で
document.body.classList.toggle("dark")を呼ぶ toggleの戻り値を使って、ボタンの文字を「ライトモード」と「ダークモード」で切り替える