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

以前、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

I’m not very good at this stuff and it’ll take me a while to figure this out myself. . . Does this mean that all themes that referred to colors before are now going to be broken?

「いいね!」 6

No, not at all. SCSS variables in themes will continue to work for a long time.

But any colors outputted via SCSS variables will stay static, i.e. they cannot be dynamically switched to a new color scheme when a browser goes from normal to dark mode. So those themes/plugins will continue to work, they just won’t be compatible with automatic dark mode switching.

「いいね!」 13

Thanks for the instructions. Is there a way to also change a background image depending on dark/light mode? (I’ve used the theme switcher component to do that.) Would a CSS class indicating the mode be possible?

「いいね!」 2

Great question, I tried this and noticed that we didn’t properly support using background images or theme variables in the special color definitions stylesheet. So I made some fixes in core, and you should be able to do this now (make sure you pull the latest core).

So, if you have two images in your theme or theme component, with SCSS vars of $bg-light and $bg-dark respectively, you can add this to your color_definitions.scss stylesheet:


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

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

And then you can use var(--custom-bg) in your regular stylesheet.

「いいね!」 8

For an image, all you need to do is the vanilla prefers-dark-theme CSS media query.

That won’t work well in all cases, because the media query is not aware of the user’s preferences. Users can disable auto-dark-mode switching, but the media query won’t be aware of that, and it will result in the background meant for the dark color scheme being rendered.

「いいね!」 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ではカスタムプロパティに対するスタイルクエリは機能しません