自動ダークモードをサポートするためにテーマとプラグインを更新する

以前、Discourse のすべての色は SCSS 変数として保存されていました。 自動ダークモードカラースキーム切り替えをサポートするために、コア内のこれらの色がカスタム CSS プロパティに変換されました。インスペクターで完全なリストを簡単に見ることができます。

テーマとプラグインは、スタイルシートで使用されているすべての $color SCSS 変数を --color CSS プロパティの同等のものに切り替える必要があります。ほとんどの場合、これは単純な検索と置換のタスクです。

-   background-color: $primary-very-low;
+   background-color: var(--primary-very-low);

ただし、テーマやプラグインが SCSS カラー関数を使用して色を暗くしたり明るくしたりするなど、色のより複雑なバリエーションを使用しているケースもあります。これらのケースでは、より複雑なリファクタリングが必要になるため、テーマやプラグインで色定義を拡張する機能を追加しました。

プラグインの場合

discourse-encrypt プラグインのこのコミットは、そのようなリファクタリングの良い簡単な例です。これは、mix($color1, $color2) SCSS 宣言を別のファイルに移動し、CSS カスタムプロパティとして保存します。次に、新しいファイルが :color_definitions アセットとして登録され、新しく宣言された色プロパティが色定義スタイルシートに含まれることが保証されます。

テーマの場合

テーマでは、common/color_definitions.scss スタイルシートで CSS カスタムプロパティを宣言することで、同じことを行うことができます。例については、graceful テーマのこのコミットを参照してください。

その他の注意事項

  • rgba($color, 0.5) 関数を介して透過色を使用する場合、SCSS は最初のパラメーターで HEX および RGB 色を受け入れますが、CSS カスタムプロパティは RGB 色のみを受け入れます。そのため、hexToRGB() ヘルパーと、色定義で --rgb サフィックスを持つ一部のプロパティを導入しました。例:
// color_definitions.scss
:root {
  --primary: #{$primary};
  --primary-rgb: #{hexToRGB($primary)};
}

// other stylesheet
.element {
  background-color: rgba(var(--primary-rgb), 0.05);
}
  • 上記のコードスニペットでは、SCSS 変数がカスタムプロパティに渡されるときに補間されます。これは SCSS の要件です。詳細については、Sass: Property Declarations を参照してください。
  • CSS の var() 宣言は、最初の値が見つからない場合に備えて 2 番目の値をフォールバックとして使用できます。つまり、var(--color1, red) と記述すると、--color1 プロパティが見つからない場合に CSS は red 色にフォールバックします。プラグインでは、以前のバージョンの Discourse との互換性を確保するために、SCSS カラー変数をフォールバックとして使用します。したがって、前の例はフォールバックを使用して次のように表示されます。
-   background-color: $primary-very-low;
+   background-color: var(--primary-very-low, $primary-very-low);

このドキュメントはバージョン管理されています - 変更の提案はgithubで行ってください。

「いいね!」 24

私はこの手のことがあまり得意ではなく、自分で理解するまで時間がかかりそうです。つまり、以前に色を参照していたすべてのテーマが、今後は動作しなくなるということでしょうか?

「いいね!」 6

いいえ、全く問題ありません。テーマ内の SCSS 変数は今後も長く機能し続けます。

ただし、SCSS 変数を通じて出力される色は静的なままとなり、ブラウザが通常モードからダークモードに切り替わった際に、新しいカラーパレットに動的に変更することはできません。そのため、これらのテーマやプラグインは引き続き動作しますが、自動的なダークモード切り替えとの互換性はありません。

「いいね!」 13

ご指示ありがとうございます。ダークモード/ライトモードに応じて背景画像を変更することも可能でしょうか?(すでにテーマ切り替えコンポーネントを使用して実現しています。)モードを示すCSSクラスを追加することは可能でしょうか?

「いいね!」 2

素晴らしい質問ですね。試してみたところ、特殊な色定義のスタイルシートで背景画像やテーマ変数の使用が正しくサポートされていなかったことに気づきました。そこでコア部分にいくつか修正を加えましたので、これで対応可能になりました(最新のコアをプルしていることを確認してください)。

例えば、テーマまたはテーマコンポーネントに $bg-light$bg-dark という SCSS 変数を持つ 2 つの画像がある場合、color_definitions.scss スタイルシートに以下を追加できます:


$bg: url(dark-light-choose($bg-light, $bg-dark));

:root {
  --custom-bg: #{$bg};
}

その後、通常のスタイルシートで var(--custom-bg) を使用できます。

「いいね!」 8

画像の場合は、標準の prefers-dark-theme CSS メディアクエリを使用するだけです。

これはすべてのケースでうまく機能するわけではありません。メディアクエリはユーザーの環境設定を認識していないためです。ユーザーは自動ダークモード切り替えを無効にできますが、メディアクエリはそのことを認識できず、結果としてダークカラースキーム用の背景がレンダリングされてしまいます。

「いいね!」 4

Discourse は、配色または配色 ID 用の CSS クラスを <body> に追加することも可能ですか?その方がはるかに簡単になるように思えます。

テーマ変換中に、多くの異なる CSS ルールと変数が必要になる問題の解決を試みていますが、color_definitions.scss ファイルが複雑な混乱状態になっています。

テーマ内の分離された SCSS ファイルで次のようなことを行うことができれば、color_definitions.scss で解決に時間がかかっていることをわずか 5 分で完了できます。

body.dark-palette .some-thing {
  // いくつかのスタイル
}

body.light-palette .some-thing {
  // いくつかのスタイル
}

グラデーションの場合、特にカラー定義ファイルに多くのコード行が含まれる可能性があります。

それでも、私の考えでは、それは最も適切な「場所」です。使用されている要素からは離れていますが、ライトモード/ダークモードに応じて切り替わる色/グラデーションを処理する便利な単一の場所です。

別の方法として、次のようなものを使用できます。

@container style(--scheme-type: light){
  body{
    background: red;
  }
}

私たちのカラー スキームには、ライト スキームの場合は light、ダーク スキームの場合は dark である --scheme-type プロパティが付属しています。最近のブラウザはコンテナー クエリをサポートしているため、これにより、ページの body にクラスを追加することなく、ここで達成しようとしていることを実行できます。

私のCSS/SCSSのスキルはあまり高くありません。これらの分野に詳しい人にはもっと簡単なことかもしれません。

color_definitions.scssファイルが散らかっていたので、インポートできるようにscss/内の別のファイルに移動しました。名前の付け方がわからないので、このようになっています。

ボディクラス(または他の例)があればもっと簡単になると思いますが、いずれにしても、今のところは機能しています。コンテナクエリの仕組みはわかりませんが、後で調べます。

なお、本日(2025/11/14)現在、Firefoxではカスタムプロパティに対するスタイルクエリは機能しません