Custom Properties o Variables CSS. Qué son y cómo funcionan

Las variables de CSS (formalmente llamadas como CSS Custom Properties) es una funcionalidad reciente de CSS que permite manejar variables de manera parecida a otros lenguajes de programación. En este artículo te lo cuento con ejemplos.
Custom Properties o Variables CSS. Qué son y cómo funcionan

Hace años CSS era un lenguaje completamente plano y hacía complicado el desarrollo. Es por eso que otros preprocesadores de CSS como LESS o SASS se hicieron populares al darle algo de dinamismo a la generación de CSS. Sin embargo, CSS se ha modernizado mucho últimamente y, desde que están disponibles las Custom Properties o Variables CSS, mucho más.

Si bien las custom properties no son estrictamente variables como las conocemos en Javascript o en otros lenguajes de programación propiamente, el apelativo de Variables de CSS ilustra bien su funcionamiento, aunque tienen algunas particularidades. Básicamente, permiten guardar un valor personalizado y usarlo a lo largo de la hoja de estilos, permitiendo modificarlo en determinados bloques.

Vamos a ver un ejemplo de las CSS Custom Properties en acción y analizar su comportamiento

Caso básico: declarar y usar las variables de CSS

Vamos a trabajar con una única custom property para empezar, pero puedes usar tantas como se te antoje o necesites. Generalmente, se suelen definir bajo el pseudoselector :root, que es básicamente el selector html pero con algo más de especifidad. Como bien sabes, CSS funciona en cascada, así que todos los elementos que cuelguen de HTML podrán heredar esta propiedad (es decir, todos).

:root {
  --my-color: black;
}
.btn {
  background-color: var(--my-color);
}

Este sencillo ejemplo es bastante ilustrador: estamos declarando una variable y usándola a lo largo de la hoja de estilos. Esto es realmente cómodo, sobre todo cuando se trabaja con temas o personalizaciones. Si tú defines tus colores corporativos "a fuego", te costará mucho reutilizar ese código CSS en otro proyecto. La reutilización de código es más sencilla empleando las Variables CSS, pues solo tendrás que cambiar una vez la definición de la variable (frente a tener que hacer múltiples buscar y reemplazar).

Sobrescribir variables CSS a través de las reglas de cascada

El propio nombre de CSS se traduce al español como "Hoja de estilos en cascada". Eso significa que, salvo excepciones, todo lo que especifiques en el padre se hereda automáticamente al hijo. Este mecanismo, llamado reglas de cascada, también afecta a las variables CSS y es por eso que podemos usarlas en cualquier punto de la hoja de estilos.

Sin embargo, teniendo en cuenta estas mismas reglas, podemos reemplazar las variables CSS en determinados bloques o selectores (y, por tanto, los hijos de estos). Te lo muestro con un ejemplo:

<div class="uno">
  <div class="dos">
    <div class="tres"></div>
    <div class="cuatro"></div>
  </div>
</div>

<style>
.dos {
  --test: 10px;
}

.tres {
  --test: 2em;
}
</style>

Tenemos que los selectores tres y cuatro son hijos de dos y, este a su vez, es hijo de uno. Más abajo tenemos el código CSS que interpretará el navegador con las variables CSS. ¿Sabrías decir cuánto valdrá la variable test en cada uno de estos divs? Vamos a analizarlo:

  • En el elemento div class="dos": 10px
  • En el elemento div class="tres": 2em
  • En el elemento div class="cuatro": 10px (heredado de su padre)
  • En el elemento div class="uno": valor no válido, porque no hemos definido ninguna variable.

De esta forma, podemos reemplazar el valor genérico de una variable para un selector concreto. Imagina una parte de tu sitio web que es ligeramente diferente al resto: con hacer un selector que rescriba la variable y sea el padre del resto de elementos, asunto resuelto.

Qué pasa cuando una variable CSS no está definida

Es posible que una custom property de CSS no esté definida en un momento dado. En la mayoría de lenguajes de programación el código explotaría, pero no es el caso en CSS. La función var de CSS admite dos parámetros: el primero es el nombre de la variable a sustituir (obligado) y el segundo, de forma opcional, el valor por defecto si no está definida. Esto es muy útil cuando es posible que la variable no esté definida previamente:

.lorem {
  color: var(--my-var, red); /* Si --my-var no está definida, será rojo */
}

.super-lorem {
  background-color: var(--my-var, var(--my-background, pink)); 
  /* Se pueden encadenar llamadas a var() una dentro de otra... */
  /* Intenta --my-var; si no existe intenta --my-background; si no existe será rosa */
}

Añadiendo dinamismo con Variables CSS desde Javascript

Javascript es omnipresente hoy en día y, por supuesto, tiene acceso de forma indirecta a las reglas CSS de un elemento, pudiendo modificar sus valores. Sin las custom properties, Javascript tendría que localizar todos los elementos que necesitamos modificar y luego, uno a uno, modificar las reglas de CSS del elemento. Por ejemplo, localizar todos los botones con cierta clase y, por cada uno, asignarles un nuevo valor: cambiar el fondo por rojo, el color por blanco, etc.

Sin embargo, teniendo en cuenta que Javascript tiene acceso a las variables de CSS, si definimos en las reglas de estilo que aplican a los elementos del DOM usando Custom Properties, tan solo habrá que cambiar el valor de dichas variables para que todos los elementos cambien.

// Obtener la variable desde el estilo inline
element.style.getPropertyValue("--my-var");

// Obtener variable desde cualquier lugar
getComputedStyle(element).getPropertyValue("--my-var");

// Establecer variable en estilo inline
element.style.setProperty("--my-var", variableJS + 4);

Diferencia entre Custom Properties y variables de SASS

CSS era un lenguaje que generalmente no se trabajaba directamente. La dificultad de mantener los elementos anidados, la falta de variables y algunas carencias más hacían de él un lenguaje duro y complicado. Es por ello que nacieron muchos preprocesadores de CSS: lenguajes que permitían muchas comodidades y que, a la hora de compilar, generaban el CSS resultante. Un ejemplo claro de ello era SASS.

SASS permitía el uso de variables evitando emplear valores literales a lo largo de la hoja de estilos y era muy cómodo para reutilizar código. Esto es un ejemplo de variable en SASS:

$var: #fff;
.lorem {  color: $var;} //Valdrá #fff

Sin embargo, hay una diferencia principal entre las variables de SASS y las variables de CSS: las variables de SASS se generan en el servidor y no se pueden reemplazar en el cliente mientras que las variables de CSS sí se pueden reemplazar en el cliente. Es decir, usando herencia y las reglas de cascada, la variable de CSS se puede modificar para un bloque concreto; las de SASS no.

Pero no por ello tenemos que decantarnos exclusivamente por un tipo de variables: se pueden usar las dos. De hecho, utilizar los dos tipos de variable es coger lo mejor de cada mundo. En este ejemplo estamos aprovechando las funciones que tiene SASS (como aclarar un color rojo un 10%) y, con ese resultado, lo "imprimimos en una variable de CSS".

Para ello, fíjate que envolvemos la variable de SASS mediante #{$varName}:

$color-link: lighten(red, 10%);

:root {  
  --color-link: #{$color-link};  
}

Cómo hacer un Dark theme con Custom Properties

Además de para cambios rápidos, las variables de CSS pueden servir para muchas más cosas. Aprovechando cómo funcionan las reglas de herencia en cascada vamos a ver un ejemplo del mundo real: cómo hacer un dark theme únicamente usando CSS.

Aunque resumido, este simple código es la base para crear un tema oscuro usando solamente las variables de CSS. Por lo general, cargará las variables de texto en color negro y el inverso en blanco. Si el navegador del usuario está configurado para cargar el modo oscuro, cargará las variables de texto en blanco y el inverso en negro.

:root {  
  --textColor: black;  
  --textColorInverse: white;
}

@media (prefers-color-scheme: dark) { 
  :root {
    --textColor: white;  
    --textColorInverse: black;
  }
}

Conclusión

Las variables de CSS o Custom Properties son una feature muy útil para el desarrollo de código en lenguaje CSS y la ventaja es que todos los navegadores modernos tienen soporte para ellas. Además, no se hace estrictamente necesario un preprocesador de CSS para poder tener algo parecido a las variables tal y como las conocemos. Permiten que el código CSS sea más legible y mantenible, y que los cambios en el diseño sean más rápidos y sencillos. Así que te invito a que las uses en tu próximo proyecto.

¡Qué tengas un feliz coding!