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

No soy muy bueno en esto y me tomará un tiempo resolverlo por mi cuenta… ¿Significa esto que todos los temas que hacían referencia a colores antes ahora quedarán rotos?

6 Me gusta

No, para nada. Las variables de SCSS en los temas seguirán funcionando durante mucho tiempo.

Sin embargo, los colores generados mediante variables de SCSS permanecerán estáticos; es decir, no se podrán cambiar dinámicamente a un nuevo esquema de colores cuando el navegador pase del modo normal al modo oscuro. Por lo tanto, esos temas y complementos seguirán funcionando, pero no serán compatibles con el cambio automático al modo oscuro.

13 Me gusta

Gracias por las instrucciones. ¿Hay alguna forma de cambiar también la imagen de fondo según el modo oscuro/claro? (He utilizado el componente de conmutador de tema para hacerlo.) ¿Sería posible usar una clase CSS que indique el modo?

2 Me gusta

Excelente pregunta. Probé esto y noté que no admitíamos correctamente el uso de imágenes de fondo o variables de tema en la hoja de estilos de definiciones de color especiales. Por lo tanto, realicé algunas correcciones en el núcleo y ahora deberías poder hacerlo (asegúrate de actualizar el núcleo a la última versión).

Así que, si tienes dos imágenes en tu tema o componente de tema, con variables SCSS $bg-light y $bg-dark respectivamente, puedes agregar esto a tu hoja de estilos color_definitions.scss:


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

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

Y luego puedes usar var(--custom-bg) en tu hoja de estilos regular.

8 Me gusta

Para una imagen, todo lo que necesitas es la consulta de medios CSS vanilla prefers-dark-theme.

Eso no funcionará bien en todos los casos, porque la consulta de medios no tiene en cuenta las preferencias del usuario. Los usuarios pueden desactivar el cambio automático al modo oscuro, pero la consulta de medios no lo detectará, lo que dará como resultado que se renderice el fondo destinado al esquema de colores oscuro.

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).