最終更新日 2024-09-25

「ブラウザ枠」や「レンダリング枠」と「ダークモード」

ここでは「ブラウザ枠」や「レンダリング枠」でカラーテーマを「ダークモード」にする、
あるいは、「秀丸本体のカラーテーマと一致させる」といったことを中心に、
そのノウハウを扱います。

「ブラウザ枠」や「レンダリング枠」中身をダークモードに対応させるのはどうするのか?

秀丸本体のカラーテーマを「HTMLファイル」に反映させるにはどうするのか?

ここではその様々なやり方を紹介します。

@media (prefers-color-scheme: dark) は使えるが秀丸本体のカラーとは一致しない

このカラーリングは秀丸のテーマとは無関係であり、
「OS」の「個人用設定」の「色」の「既定のアプリの色」が「ライト」なのか「ダーク」なのかで決まります。

無関係とはいえ、それなりに高確率で一致させている人も多いでしょうから、
これで用が足りると踏むのもひとつの考え方です。

具体的には、「OS」では「既定のアプリ」はダークモードだが、「秀丸」は通常の「ライトモード」という場合に、
両者のテーマが食い違うということは年頭においておいてください。

test.html
<html>
<head>
<style>
@media (prefers-color-scheme: dark) {
    :root {
        color-scheme: dark;
    }
    body {
        background-color:#222277;
    }
}
@media (prefers-color-scheme: light) {
    :root {
        color-scheme: light;
    }
    body {
        background-color:#ffffee;
    }
}

</style>
</head>
<body>
<form method="post" action="#">
  <button type="submit">更新</button>
</form>
あああ
<a href="aaa">bbbb</a>
<script>
</script>
</body>
</html>
    

OSの色の「アプリの既定色」が「ライト」ならライト

OSの色の「アプリの既定色」が「ダーク」ならダーク

@media (prefers-color-scheme: light) は秀丸とは無関係

このため、「秀丸」ではなく、「OSでの色の設定」の変更に反応して、即座に切り替わります。

強制的にダークモードのカラーリングにする

HTMLを以下のようにすることで「全てのHTML要素」に関して、
ブラウザコンポーネント(Chronium)が想定しているダークモード時のカラーリングとはこうだ!!」というカラーテーマ一式に切り替わります。

この方式は、一般のブラウザでも同じです。

test.html
<html>
<head>
<style>
:root { color-scheme: dark; }
</style>
</head>
<body>
ああああ<br>
<a href="bbb">リンク</a>
</body>
</html>

強制的にダークモードのカラーリングにしつつ一部だけ変更

test.html
<html>
<head>
<style>
:root { color-scheme: dark; }
body { background-color: #222266; }
</style>
</head>
<body>
ああああ<br>
<a href="bbb">リンク</a>
</body>
</html>

秀丸本体のマクロからカラー情報を伝達する

秀丸本体から伝える場合は、ブラウザ枠( or レンダリング枠)を開く際に、
カラーリング情報を伝えるのが良いでしょう。

.mac 側 から URLでカラー情報を伝達

test.mac
jsmode "WebView2";

js {
    // 対象のHTML
    let targetfile = `${currentmacrodirectory()}\\test.html`;

    // URLオブジェクトに直す
    let absoluteUrl = new URL(targetfile);

    // GETパラメターとして darkmode=1 という形で追加
    let params = new URLSearchParams();
    params.set('darkmode', darkmode());
    absoluteUrl.search = params.toString();

    // 個別ブラウザ枠として開く
    browserpanecommand(
    {
        target: "_each",
        url : absoluteUrl,
        initialize: "async",
        show: 1
    }
    );
}

.html 側 で URLからカラー情報を受け取り、CSSを構築して反映

HTML側では、****.html?darkmode=1 というパラメータを見て、テーマカラーをスイッチします。

test.html
<html>
<head>
<style>
</style>
</head>
<body>
ああああ<br>
<a href="bbb">リンク</a>
<script>
const urlSearchParams = new URLSearchParams(window.location.search);
const isDarkModeEnabled = urlSearchParams.get('darkmode');

if (isDarkModeEnabled == 1) {
    const darkModeStyle = document.createElement('style');
    darkModeStyle.textContent = ':root { color-scheme: dark; }';
    document.head.appendChild(darkModeStyle);
}
</script>
</body>
</html>

ライトモードとダークモードで、切替が単純なら、CSSの「light-dark」という指定が役立つ

ほとんど知られていない機能として、light-darkという機能がCSSに存在します。
これにより「ライトモードならこの色、ダークモードならこの色」といった単純な指定
が出来ます。

一般的なWebサイトはこのような単純な指定はしないため、まず使われることはありませんが、
秀丸のブラウザ枠やレンダリング枠目的ならカラーリングはごく単純でしょうから、
有力な実装方法の1つでしょう。

.mac 側 から URLでカラー情報を伝達

test.mac
jsmode "WebView2";

js {
    // 対象のHTML
    let targetfile = `${currentmacrodirectory()}\\test.html`;

    // URLオブジェクトに直す
    let absoluteUrl = new URL(targetfile);

    // GETパラメターとして darkmode=1 という形で追加
    let params = new URLSearchParams();
    params.set('darkmode', darkmode());
    absoluteUrl.search = params.toString();

    // 個別ブラウザ枠として開く
    browserpanecommand(
    {
        target: "_each",
        url : absoluteUrl,
        initialize: "async",
        show: 1
    }
    );
}

light-dark(... , ...)を使うことで両カラーを簡易にカスタムする

test.html
<html>
<head>
<style>
body {
    text: light-dark(#00000, #eeeeff);
    background-color: light-dark(#ffffff, #222255);
}
</style>
</head>
<body>
あああ
<a href="aaa">bbbb</a>
<script>
const urlSearchParams = new URLSearchParams(window.location.search);
const isDarkModeEnabled = urlSearchParams.get('darkmode');

if (isDarkModeEnabled == 1) {
  const darkModeStyle = document.createElement('style');
  darkModeStyle.textContent = ':root { color-scheme: dark; }';
  document.head.appendChild(darkModeStyle);
}
この</script>
</body>
</html>

さらに洗練し、HTMLのルートに属性を付ける方法

「CSSのcolor-scheme」自体をJavaScriptで生成する、というのは、
あまりスマートな方法とは言えません。

JavaScript は HTML のルート要素に "light" または "dark" という属性を設定する役割に徹し、
実際のデザインの切り替えは CSS に任せるのが良いでしょう。

.mac 側 から URLでカラー情報を伝達

test.mac
jsmode "WebView2";

js {
    // 対象のHTML
    let targetfile = `${currentmacrodirectory()}\\test.html`;

    // URLオブジェクトに直す
    let absoluteUrl = new URL(targetfile);

    // GETパラメターとして darkmode=1 という形で追加
    let params = new URLSearchParams();
    params.set('darkmode', darkmode());
    absoluteUrl.search = params.toString();

    // 個別ブラウザ枠として開く
    browserpanecommand(
    {
        target: "_each",
        url : absoluteUrl,
        initialize: "async",
        show: 1
    }
    );
}

HTMLのルートに属性「hm-theme-color」という属性を付け、「"dark"」か「"light"」を設定する。
その値によってCSS自身が自動で振り分ける

test.html
<html>
<head>
<style>
[hm-theme-color="dark"] {
    color-scheme: dark;
}
[hm-theme-color="light"] {
    color-scheme: light;
}
</style>
</head>
<body>
あああ
<a href="aaa">bbbb</a>
<script>
const urlSearchParams = new URLSearchParams(window.location.search);
const isDarkModeEnabled = urlSearchParams.get('darkmode');

if (isDarkModeEnabled == 1) {
    document.documentElement.setAttribute('hm-theme-color', "dark");
} else {
    document.documentElement.setAttribute('hm-theme-color', "light");
} 
</script>
</body>
</html>

一度渡したカラーテーマ情報が維持されるようにする

一度 HTMLを表示した後、(HTML内に「ボタン」があるなどで)ブラウザ枠をクリックするなどで
ページが更新されると、URLのdarkmodeパラメータが無くなり
darkmode=1のパラメータが無くなり、ダークモードが解除されてしまうかもしれません。

この問題を解決するには、sessionStrageを使うのがよいでしょう。

.mac 側 から URLでカラー情報を伝達

test.mac
jsmode "WebView2";

js {
    // 対象のHTML
    let targetfile = `${currentmacrodirectory()}\\test.html`;

    // URLオブジェクトに直す
    let absoluteUrl = new URL(targetfile);

    // GETパラメターとして darkmode=1 という形で追加
    let params = new URLSearchParams();
    params.set('darkmode', darkmode());
    absoluteUrl.search = params.toString();

    // 個別ブラウザ枠として開く
    browserpanecommand(
    {
        target: "_each",
        url : absoluteUrl,
        initialize: "async",
        show: 1
    }
    );
}

一度 darkmodeを伝達すれば、sessionStrageに保持し、該当のブラウザ枠を閉じるまでは保持する

test.html
<html>
<head>
<style>
[hm-theme-color="dark"] {
    color-scheme: dark;
}
[hm-theme-color="light"] {
    color-scheme: light;
}
</style>
</head>
<body>
あああ
<a href="aaa">bbbb</a>
<script>
const urlSearchParams = new URLSearchParams(window.location.search);
const isDarkModeEnabled = urlSearchParams.get('darkmode');

// カラーが明示されたら、セッションストレージを更新
if (isDarkModeEnabled) {
	targetColor = isDarkModeEnabled==1 ? 'dark' : 'light';
    sessionStorage.setItem("hm-theme-color", targetColor)

// カラーが明示されてなければ、セッションストレージからロード
} else {
    targetColor = sessionStorage.getItem("hm-theme-color");
}

// 対象のテーマカラーで表示
document.documentElement.setAttribute('hm-theme-color', targetColor);
</script>
</body>
</html>