Actualizar temas y plugins para soportar modo oscuro automático

Anteriormente, todos los colores en Discourse se almacenaban como variables SCSS. Para admitir el cambio automático de esquema de color del modo oscuro, hemos convertido estos colores en el núcleo a propiedades CSS personalizadas. Ahora puede ver fácilmente la lista completa en el inspector:

Los temas y complementos deben cambiar todas las variables SCSS $color utilizadas en las hojas de estilo por los equivalentes de propiedad CSS --color. En la mayoría de los casos, esta es una simple tarea de buscar y reemplazar:

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

Pero hay algunos casos en los que un tema o un complemento está utilizando una variación más compleja de un color, por ejemplo, al oscurecer o aclarar usando funciones de color SCSS. Estos casos requieren una refactorización más compleja, y para esto hemos agregado la capacidad de extender las definiciones de color en temas y complementos.

En complementos

Este commit en el complemento discourse-encrypt es un buen y simple ejemplo de dicha refactorización. Mueve una declaración SCSS mix($color1, $color2) a un archivo separado y la almacena como una propiedad personalizada de CSS. Luego, el nuevo archivo se registra como un activo :color_definitions, lo que garantiza que la propiedad de color recién declarada se incluya en la hoja de estilo de definiciones de color.

En temas

En los temas, puede hacer lo mismo declarando propiedades personalizadas de CSS en la hoja de estilo common/color_definitions.scss. Puede consultar este commit en el tema graceful para ver un ejemplo.

Algunas notas adicionales

  • cuando se utilizan colores transparentes a través de la función rgba($color, 0.5), SCSS acepta colores HEX y RGB en el primer parámetro, mientras que las propiedades personalizadas de CSS solo aceptan un color RGB. Es por eso que hemos introducido el ayudante hexToRGB() y algunas propiedades con el sufijo --rgb en las definiciones de color. Un ejemplo:
// color_definitions.scss
:root {
  --primary: #{$primary};
  --primary-rgb: #{hexToRGB($primary)};
}

// other stylesheet
.element {
  background-color: rgba(var(--primary-rgb), 0.05);
}
  • tenga en cuenta que en el fragmento anterior, la variable SCSS se interpola cuando se pasa a una propiedad personalizada. Este es un requisito en SCSS, consulte Sass: Property Declarations para obtener más detalles.
  • la declaración CSS var() puede tener un valor de reserva si el primero no está disponible, como al escribir var(--color1, red), CSS recurrirá al color rojo si no se encuentra la propiedad --color1. En los complementos, utilizamos las variables de color SCSS como valores de reserva para garantizar la compatibilidad con versiones anteriores de Discourse. Por lo que el ejemplo anterior, se vería así con un valor de reserva:
-   background-color: $primary-very-low;
+   background-color: var(--primary-very-low, $primary-very-low);

Este documento tiene control de versiones: sugiera cambios en github.

24 Me gusta

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 Me gusta

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 Me gusta

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 Me gusta

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 Me gusta

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 Me gusta

¿Es posible que Discourse también agregue una clase CSS a la etiqueta <body> para el esquema de color o el ID del esquema de color? Parece que sería mucho más fácil.

Estoy tratando de resolver un problema durante la conversión de un tema donde necesito muchas reglas CSS y variables diferentes, y se está convirtiendo en un lío complejo en el archivo color_definitions.scss.

Si pudiera hacer algo como esto en un archivo SCSS aislado en el tema, me tomaría 5 minutos hacer algo que está tardando mucho en resolverse con color_definitions.scss:

body.dark-palette .some-thing {
  // algunos estilos
}

body.light-palette .some-thing {
  // algunos estilos
}

Sí, puedes terminar con muchas líneas de código en los archivos de definición de color, particularmente para los degradados.

Sigue siendo el “lugar” más apropiado en mi opinión. Está alejado del elemento donde se usa, sí, pero es un lugar único y conveniente que maneja colores/degradados que cambian según el modo claro/oscuro.

Una alternativa es usar algo como esto:

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

Nuestros esquemas de color vienen con una propiedad --scheme-type que es light para esquemas claros y dark para esquemas oscuros. Los navegadores recientes admiten consultas de contenedor, por lo que esto debería hacer lo que intentas lograr aquí sin agregar una clase al cuerpo de la página.

Mis habilidades de CSS/SCSS no son geniales. Quizás esto sea más fácil para personas que están muy metidas en esas cosas.

Estaba creando un desastre en el archivo color_definitions.scss, así que lo moví a otro archivo en scss/ para poder importarlo. No estoy seguro de cómo nombrar todo, así que se ve así.

Creo que sería más fácil hacerlo con una clase de cuerpo (o quizás algunos ejemplos más), pero en cualquier caso, está funcionando por ahora. No sé cómo funcionan las consultas de contenedor, pero lo investigaré más tarde.

Tenga en cuenta que las consultas de estilo para propiedades personalizadas no funcionan en Firefox a día de hoy (14/11/2025).