Te vamos a enseñar cómo crear theming con el uso de las variables CSS no sin antes explicar algunos conceptos básicos sobre los modelos de colores que se usan para el desarrollo web. El objetivo final es crear un tema claro y un tema oscuro contribuyendo así a la configuración de apariencia del dispositivo del usuario, además de poder pasar de uno a otro a través de un botón y guardar la preferencia para la próxima visita.

El año 2019 fue el año del Dark Mode, anunciado por primera vez en la Google I/O Conference con la denominación Dark Theme para Android y acto seguido en la WWDC Conference con la denominación Dark Mode para iOS.

En Cupertino lo anunciaban como un “nuevo y dramático aspecto que ayuda a centrarte en tu trabajo” al igual que “un ambiente libre de distracciones”. Sin embargo Google lo llevó al terreno más funcional definiéndolo un modo sostenible ya que reduce considerablemente el uso de energía a la vez que aumenta de forma significativa la accesibilidad para aquellos usuarios con baja visión o sensibles a la luz.

Al final de este insight vamos a valorar cuáles de estas afirmaciones son ciertas y cuáles no con la ayuda de una experta en accesibilidad.

 

Quiero ser Dark Mode

Hoy en día muchas aplicaciones para smartphone soportan el modo oscuro, al igual que los sistemas operativos desktop o algunas de sus aplicaciones como Chrome, Firefox y Slack entre otras.

Si tú también quieres ser dark mode, estás en el insight oportuno. Aprenderás a crear un tema utilizando las Custom Properties. Las custom properties son propiedades dinámicas ya que se pueden cambiar o sobrescribir en cualquier momento en función de las preferencias del usuario. En el momento que se produce dicho cambio o se sobrescribe el valor de una custom property, todos los elementos que la usan automáticamente mostrarán ese cambio.

Para este propósito creamos un componente que llamamos card, sin embargo antes vamos a conocer el modelo de color más adecuado para conseguirlo.

1
Dark mode con CSS

El modelo HSL

Para empezar a manipular un color la mejor forma es representarlo con el modelo HSL (hue, saturation, lightness). ¿El motivo? Porque es el modelo más intuitivo y sencillo para los humanos a la hora de saber cómo será el color cuando cambian algunos de los tres valores.

HSL es fácil de modificar y para improvisar nuevos colores, de hecho convertirse en maestros de HSL tardamos pocos minutos, tan solo es comprender cómo funciona.  

 

hsl(205, 100%, 50%)

 

El color está determinado por el tono (H) que representa el grado en la rueda de color: de 0 (cero) a 360, donde 0 es rojo, 120 verde y 240 azul. El segundo valor (100%) representa la saturación (S), que va de 0 a 100, donde 100 representa la saturación máxima. El tercer y último valor (50%) define la luminosidad (L) que va de 0 a 100; cero representa un color sin luminosidad (negro) y 100 el máximo de su luminosidad (blanco).

La siguiente rueda de colores nos da una información más concreta de cómo funciona el método HSL. Para definir un nuevo color solamente hemos de asignar un nuevo grado. Una herramienta rápida para definir un color puede ser HSL Calculator o directamente desde la Developer Tools de Chrome o Firefox.

2
Dark mode con CSS

Manipular colores con variables CSS

Aclarado el por qué usar el modelo HSL es más efectivo que el modelo RGB o el modelo HEX, componemos nuestra paleta de colores basadas en variables CSS. El sistema de diseño que vamos a crear es un sistema totalmente flexible y preparado para reproducir cualquier theming.

Consideramos el azul como color de base.


:root {
  // HSL
  --hue: 205;
  --saturation: 100%;
  --lightness: 50%;

// Color palette
  --primary-color: hsl(var(--hue), var(--saturation), var(--lightness));
  --secondary-color: hsl(calc(var(--hue) + 180), var(--saturation), var( --lightness));
}

Tenemos un color primario que llamamos --primary-color y un color secundario complementario que llamamos --secondary-color. Un color complementario es aquel color que se encuentra en la parte opuesta de la rueda de colores, es decir girando 180 grados tal y como se ha calculado en la variable (+ 180).

La parte emocionante de las custom properties es la capacidad de aprovechar el comportamiento estándar de CSS: la herencia y la cascada, algo que no podemos hacer con las variables de un preprocesador como Sass o Less. Cuando el valor cambia, el navegador actúa en consecuencia.

Para comprender mejor el concepto vamos hacer una prueba muy sencilla con este pen que calcula los colores complementarios. Modificamos la variable --hue con un valor que va de 0 a 360 y automáticamente nos calculará su color complementario. Juega modificando saturación y luminosidad.

¿Te ha quedado claro cómo actúa una variable CSS cuando cambia su valor? Volvamos entonces a nuestro ejemplo inicial y empezamos a crear nuestro componente card en su versión light y dark.

3
Dark mode con CSS

¡Empezamos!

El primer paso es extraer todos los colores que van a ser sometidos al cambio y declararlos como variables. Cuando creamos diferentes temas también debemos considerar modificar la tipografía (estilo, tamaño, grosor...), o incluso aumentar los espacios blanco/oscuros alrededor del texto con el propósito de mantener una legibilidad agradable en todas las versiones.

Para nuestro componente no solo vamos a crear variables de colores sino también variables de otras propiedades de estilo. Sin embargo, para no extender demasiado el fragmento de código a continuación, solamente se representan las variables de colores. Prestar atención como todas tienen un denominador común: la misma base de cálculo formada por las variables --hue, --saturation y --lightness.


:root {
  
  /* HSL */
  --hue: 205;
  --saturation: 100%;
  --lightness: 50%;
  
  /* Color palette */
  --primary-color: hsl(var(--hue), var(--saturation), var(--lightness));
  --secondary-color: hsl(calc(var(--hue) + 180), var(--saturation), var( --lightness));
  
  /* Scaffolding */
  --body-bg: hsl(var(--hue), calc(var(--saturation) * 0), calc(var(--lightness) * 5));
  
  /* Card */
  --card-border-color: hsla(var(--hue), calc(var(--saturation) * 0), calc(var(--lightness) * 1.8), 1);
  --card-text-color: hsl(var(--hue), calc(var(--saturation) * 0), calc(var(--lightness) * 0.7));
  --card-link-color: hsl(calc(var(--hue) + 180), var(--saturation), calc(var( --lightness) * 3));
}

Y ahora hagamos que suceda la magia haciendo uso de la característica prefers-color-scheme introducida en Media Queries Level 5. Esta propiedad captura la configuración del usuario para mostrar la página en versión dark o light independientemente de si se ha aplicado a todo el sistema operativo o solamente al navegador.

Los valores admitidos para esta propiedad son: no-preference, light y dark. Esto significa que podemos configurar el aspecto por defecto, en nuestro caso light.

Duplicamos el grupo de variables declarado anteriormente y modificamos los valores cambiando el multiplicador. En este caso, por una cuestión de gusto, también se ha modificado el valor del tono (--hue) y la luminosidad (--lightness).


@media (prefers-color-scheme: dark) {
  :root {
    
    /* HSL */
    --hue: 120;
    --lightness: 70%;
    
    /* Scaffolding */
    --body-bg: hsl(var(--hue), calc(var(--saturation) * 0), calc(var(--lightness) * 0.25));
    
    /* Card */
    --card-bg: hsl(var(--hue), calc(var(--saturation) * 0), calc(var(--lightness) * 0.325));
    --card-border-color: hsla(var(--hue), calc(var(--saturation) * 0), calc(var(--lightness) * 1.8), 0.05);
    --card-text-color: hsl(var(--hue), calc(var(--saturation) * 0), var(--lightness));
    --card-link-color: hsl(calc(var(--hue) + 180), var(--saturation), calc(var( --lightness) * 1.1));
  }
}

En este pen puedes ver el ejemplo completo: Dark Mode in CSS. Siéntete libre de usarlo y mejorarlo.

Dark mode y accesibilidad

El modo oscuro desde luego tiene un impacto positivo en cuestión de accesibilidad pero también ha creado afirmaciones no del todo ciertas. La experta en accesibilidad Sheri Byrne-Haber ha recopilado una serie de sentencias que ha categorizado en “definitivamente cierto”, “no del todo cierto” y “no cierto”.

Su investigación concluye afirmando que para algunas personas los temas oscuros sí son más accesibles. Estos beneficios no son relacionados con el tema en sí, sino más bien con el dispositivo en el que está activo el modo oscuro, así como situaciones personales de cada usuario debido a su entorno o discapacidad.

A la hora de diseñar un tema, claro o oscuro que sea, hay que considerar la legibilidad de los contenidos lo cual afecta al color del texto, su tamaño y grosor. Es un requisito mínimo por cumplir con los criterios 1.4.3 Contrast (Minimum) y 1.4.11 Non-text Contrast de las WCAG 2.1.

Dark mode y usabilidad

Otro aspecto a tener en cuenta a la hora de implementar un tema oscuro es la experiencia de usuario. El cambio entre el tema claro y el tema oscuro ha de ser evidente y fácil de encontrar, además de “no hacer trabajar el usuario” guardando la preferencia de configuración para la próxima visita.

En este otro ejemplo se ha creado un botón que permite pasar de un tema claro a un tema oscuro. La preferencia se almacena en la propiedad localStorage para que se aplique la próxima vez que visitamos la página.