寝ながらブログをだらだら読みたい!!!!! のでダークモードを実装することにしました。
凝ったことやお金のかかることはしたくないので、質より手軽さを重視し、かんたんにできるやつにしました。
- 自分で色を決めたりせず、元の色を参照し反転させる(cssのfilterを使う)
- WordPressにJavaScript+html+cssでパッと実装
- 詰めは甘い(ところどころ見にくかったりする)
SWELLを使っている方はたぶんそのまま使えます。そうでない方もちょっと手を加えればほぼコピペでいけるんじゃないかと。
参考になりそうな部分があれば是非お試しください。
ダークモードのプラグインを使う方法(→不採用)
とりあえずラクしたかったので、まずはプラグインを試しました。
WP Dark Modeというプラグインを使うと、元の色を参照していい感じのダークモードに切り替えできるようになったのですが、
WP Dark Modeを使ったダークモードのスクショ
liner-gradientを使って表現するマーカーの装飾(←これ)と致命的に相性が悪くて諦めました。
.wp-dark-mode-active span.swl-marker.mark_orange.wp-dark-mode-ignore{
background: linear-gradient(transparent 70%,#696969 0%);
}
こんな感じのcssで対策できる…といえばできるのですが、
ダークモードに切り替えたときは問題ないのですが、そのまま別のページに移動すると効かずに戻ってしまうようで。
他にも装飾用ブロックの色が一部変わらなかったり、それを確認して直すのも億劫だったので、
導入を見送りました。
こちらのプラグインはダークモード切り替えのボタンの種類が多く、独自タグで呼び出せるので利便性も高く、
floating switchも選べて可愛かったのですが、初期設定だとSWELLの上にスクロールするボタンとすごく干渉していました。
これもcss書けば直せるのかな? 確認はしてないです。
CSSのfilterとJavaScriptを使う方法(→採用)
色を反転できるfilterを使う方法にたどり着きました。
cssをちょっと書き、htmlにボタンを置き、JavaScriptでボタンごとに切り替えられるようにする。簡単そう!!
……って思ったけど導入先がWordPressであることの相違などもあるのか、そのままでは動かず、
最終的にめちゃくちゃChatGPTに聞きながらなんとかしました。天才だよあんた…。
こういう融通も効くのありがたすぎました。
ダークモードのcss
html[data-mode="dark"] {
filter: invert(0.8) hue-rotate(180deg);
}
html[data-mode="dark"] img {
filter: invert(1) hue-rotate(180deg);
}
html[data-mode="dark"] iframe {
filter: invert(1) hue-rotate(180deg);
}
お使いのcssファイルや、カスタマイズ>追加cssにそのまま書いちゃえばOKです。下記は説明です。
- invert
-
色反転の度合いの数値を指定するところ。0が効果なし、1だと完全にかかります。
当ブログの背景がほぼ完全な白であることもあり、真っ黒すぎる気がしたので、
全体(html)のinvertを0.8にしてまろやかにしてあります。好みで数値をいじると良いと思います。 - hue-rotate
-
こちらは色相環の反転の指定。180度(正反対)にしときました。
- img
-
画像ごと反転されるので画像は再度反転させて色味を戻します。
- iframe
-
サイト内の画像の色味はimgで指定すれば戻せるのですが
外部サイトの画像(広告や埋め込んだSNS、YouTubeなどの画像)が反転したままだったので
iframeも再度反転させてみたところ解決した気がするのでこうしておきました。
大雑把すぎて何か変なことが起きそうな気もしますがかんたんダークモードなので気にしない!
色を暗くする機能ではなく反転させる機能を使っているので、元のページで暗いところは反対に明るくなります。
サイトのデザインにあわせて検討したほうが良さそうです。
このあと、ボタン2つ版とボタン1つ版をご紹介しますが、このcssは変えずにそのまま使えます。
ボタン2つ版
JavaScript
document.addEventListener('DOMContentLoaded', function() {
// 初期状態の設定
applySavedMode();
// light1クラスのボタンにクリックイベントリスナーを追加
const lightButtons = document.querySelectorAll('.light1');
lightButtons.forEach(function(button) {
button.addEventListener('click', function() {
setModeLocalStorage('light');
applySavedMode();
});
});
// dark1クラスのボタンにクリックイベントリスナーを追加
const darkButtons = document.querySelectorAll('.dark1');
darkButtons.forEach(function(button) {
button.addEventListener('click', function() {
setModeLocalStorage('dark');
applySavedMode();
});
});
});
// ローカルストレージにモードを保存する
function setModeLocalStorage(mode) {
localStorage.setItem('data-mode', mode);
}
// ローカルストレージからモードを読み込んで適用する
function applySavedMode() {
const savedMode = localStorage.getItem('data-mode');
if (savedMode === 'light') {
document.documentElement.setAttribute('data-mode', 'light');
} else if (savedMode === 'dark') {
document.documentElement.setAttribute('data-mode', 'dark');
}
}
コメントアウトに至るまで全部ChatGPTが書いてくれたコードです。なんてこった。
html(+css)
SWELLは外観>カスタマイズ>高度な設定からbodyタグ終了直前に出力するコードを編集できるので、そこで読み込みます。
<script type="text/javascript" src="上記のJSファイル"></script>
htmlはカスタムhtmlブロックをウィジェット内に置いて使います。
メニュー内で読み込みたかったんですが、メニューにはカスタムhtmlブロックが使えないんですね…。
PC用はヘッダー内部、スマホ用はスマホ開閉メニュー下に表示することにしました。
<div class="modebutton">
<button class="dark1" data-mode="dark">ボタン</button>
<button class="light1" data-mode="light">ボタン</button>
</div>
コードは2か所とも同じです。
上記はボタンを2つ用意しているバージョンで、私の場合はSWELLの標準機能で使える電球の絵文字を使ってあります。
これ→
使わない場合やSWELLじゃない場合は任意の文字列に変えてください。
それぞれにcssも書いてみました。
ボタンの装飾css(使わなくていいのでたたんでおきます)
.dark1,.light1{
background:transparent;
border:none;
font-size:110%;
border-radius:50%;
box-sizing:border-box;
}
.dark1:hover{
background:#333;
color:#fff;
transition:0.5s;
}
.light1:hover{
transition:0.5s;
box-sizing:border-box;
box-shadow:0 0 0 1px #333 inset;
}
.modebutton{
width:fit-content;
margin:0 auto;
padding:5px;
border:1px solid #444;
border-radius:15px;
box-sizing:border-box;
}
結構かわいいんじゃないでしょうか。
ボタン1つ版
cssまで書いといてなんですが、ボタンはひとつでもダークモードとの切り替えができるしその方がスムーズな気がしたので
さらにchatGPTに教えてもらってボタン1つ版も用意しました。
こっちの方がコードも短いしこれでいいな…。になりました。
Javascript
document.addEventListener('DOMContentLoaded', function() {
const toggleButtons = document.querySelectorAll('.toggle-mode');
toggleButtons.forEach(function(button) {
button.addEventListener('click', function() {
const currentMode = localStorage.getItem('data-mode');
const newMode = currentMode === 'dark' ? 'light' : 'dark';
localStorage.setItem('data-mode', newMode);
applySavedMode();
});
});
// 初期状態の設定
applySavedMode();
});
// ローカルストレージからモードを読み込んで適用する
function applySavedMode() {
const savedMode = localStorage.getItem('data-mode');
if (savedMode === 'light') {
document.documentElement.setAttribute('data-mode', 'light');
} else if (savedMode === 'dark') {
document.documentElement.setAttribute('data-mode', 'dark');
}
}
html(+css)
<script type="text/javascript" src="上記のJSファイル"></script>
jsファイルの読み込みは上記例と同じようにし(外観>カスタマイズ>高度な設定)、
ウィジェット(PC用はヘッダー内部、スマホ用はスマホ開閉メニュー下)のカスタムhtmlブロックでボタンのコードを置きます。
<button class="toggle-mode">ボタン</button>
ボタンの装飾css(使わなくていいのでたたんでおきます)
.toggle-mode{
background:transparent;
border:none;
font-size:110%;
border-radius:50%;
box-sizing:border-box;
box-shadow:0 0 0 1px #333 inset;
}
.toggle-mode:hover{
background:#333;
color:#fff;
transition:0.5s;
}
ということで当ブログでは当初ボタン2つ版を使っていましたが現在は1つ版を使っております。
PC(ヘッダー内)
スマホ(メニューの下部)
そしてマーカー
見やすくはないけど文字が見えるからヨシ!
まとめ
- ダークモード用のcssを用意する(追加cssに数行追加)
- Javascriptを用意してカスタマイズ>高度な設定で読み込む
- ボタンのhtmlを用意してウィジェット内にカスタムhtmlブロックとして読み込む
- PCはヘッダー内部、スマホはスマホメニュー開閉下
- お好みでボタンの装飾用cssも用意する
という感じで当ブログには簡易ダークモードが実装できました。
細かくcssで配色決めたりしてない割には、寝る前に布団の中で読みたいときとか結構快適!
SWELL本体の機能としてダークモードの実装は予定されてないようなので、どうにか対処できて良かったです。