Variables CSS

El lenguaje CSS ha sufrido unas cuantas mejoras desde que la especificación de su versión número tres salió a la luz. De entre las mejoras, siempre he estado siguiendo de reojo a la evolución de las variables CSS, puesto que suponen un gran avance en la editabilidad y escalabilidad de los códigos CSS. Considero que esta característica ha madurado lo suficiente y tiene el soporte necesario por parte de los navegadores más corrientes para poder ser utilizado a día de hoy. Es por ello que os vengo a informar sobre ella y a enseñaros, de forma general, cómo utilizarla.

¿Qué son y para qué sirven?

Las variables en CSS se comportan de forma semejante a las variables de muchos lenguajes de programación (¡ojo! no estoy diciendo que CSS sea un lenguaje de programación). Si nunca has programado, quizás lo mejor sea que las relaciones con las variables de matemáticas (vienen a ser prácticamente lo mismo). Su función es la de guardar un valor detrás de un nombre, para poder utilizar ese mismo valor en otros sitios sin tener que utilizar directamente el valor (esto último se conoce como «hardcoding» y se considera una mala práctica en los lenguajes de programación), sino el nombre del valor. Las ventajas que esto supone es, por ejemplo, si el diseño de la página tiene varios colores que repetimos constantemente, poder enlazarlos en una variable. En caso de que en el futuro quisiésemos cambiar ese color, tan solo tendríamos que cambiar el valor de la variable en su definición, en vez de tener que cambiar todas las veces que hayamos usado el color en nuestro seguramente quilométrico archivo CSS. Sin embargo, las variables tienen un montón más de posibilidades. Desde cambiar el color de toda una página con solo una línea de JS hasta hacer la vida más fácil a la hora de desarrollar páginas «responsive».

¿Cómo funciona?

Las variables se deben definir (darles valor) en un elemento, como si lo fuésemos a modificar con CSS como siempre, pero esta vez solo le vamos a dar un valor a una variable. Como las variables en CSS tienen ámbito dinámico («dynamic scope»), este valor se conservará para todos los hijos del elemento en donde lo hayamos definido. Es decir, que si por ejemplo tenemos la siguiente estructura HTML:
<div class="contenedor">
    <div class="hijo"></div>
    <div class="hijo"></div>
</div>
<div class="otrocontenedor"></div>
Si aplicamos la definición de variables en .contenedor y usásemos el valor de la variable en cualquiera de los hijos, el valor sería el mismo. Sin embargo, si quisiésemos utilizar la variable en .otrocontenedor, no tendríamos ningún valor. Dicho esto, cabe decir que si quisieses que las variables tuviesen un ámbito global, tendrías que definirla en el elemento padre de todo tu documento (sí, la etiqueta html). Sin embargo, como CSS es un lenguaje genérico, la forma correcta de acceder a ella sería con el siguiente selector:
:root {

Sintaxis

La sintaxis de la definición de variables es muy similar a la de la modificación de un atributo. ¡Incluso se colocan en el mismo sitio que la modificación de atributos! Véase:
--mi-variable: valor;
Entonces, si por ejemplo quisiésemos crear la variable «color-principal», que contendría el color principal de la página y que fuese accesible globalmente (en cualquier parte de nuestro documento CSS), tendríamos que colocar lo siguiente:
:root {
    --color-principal: #ff0000;
    /* Aquí podrías seguir añadiendo definiciones globales */
}
Ahora podríamos acceder a dicho valor en cualquier parte de nuestro código con la función var():
body {
    background-color: var(--color-principal);
}

.panel1, .panel2 {
    color: var(--color-principal);
}
Sin embargo, tened en cuenta que se puede cambiar el valor de una variable en el documento. Si después de una definición somos más específicos, por ejemplo, si tenemos la siguiente estructura HTML y el siguiente CSS, veremos en los comentarios de este último que la misma variable toma distintos valores: HTML:
<div class="contenedor">
    <div class="hijo"></div>
    <div class="hijo"></div>
</div>
<div class="otrocontenedor"></div>
CSS:
:root {
    --borde-principal: 1px solid #ff00ff;
}

.contenedor {
   --borde-principal: 3px dotted #00ff00; /* lo mejor sería separar las definiciones de variables de los atributos normales de CSS por claridad */
    border: var(--borde-principal); /* aquí el valor es 3px dotted #00ff00 */
}

.contenedor .hijo {
    border: var(--borde-principal); /* aquí el valor también es 3px dotted #00ff00 */
}

.otrocontenedor {
    border: var(--borde-principal); /* guess what, aquí el valor es 1px solid #ff00ff */
}

A tener en cuenta

  • Las variables no deben ser utilizadas para sustituir todos los valores. Intenta utilizarlas solo en aquellos sitios donde un valor tenga posibilidad de repetirse o donde sea lógico utilizarla. Para el resto, sigue utilizando la definición directa de valores, como siempre.
  • La función var() tiene posibilidad de «callback». Es decir, podemos separar con comas tantos valores como queramos para, en caso de que el de la izquierda no esté definido, se utilice el (o los) siguientes. Por ejemplo:
    .elm {
        color: var(--variable1, --variable2, red); /* en este caso el color sería rojo si ninguna de las anteriores estuviesen definidas en el ámbito de .elm */
    }
  • Las variables se pueden modificar con JS, por lo que hacer cosas como cambiar el color principal de todo un diseño dependiendo de cualquier condición se puede hacer con tan solo una línea de JS.
  • El soporte de las variables tiene un estado bastante saludable si se siguen valores de soporte normal (versión actual y versión actual -1 de los navegadores más comunes). Navegadores como IE o Opera Mini no lo soportan aún, aunque en el caso del primero el navegador ya no se sigue desarrollando (su sucesor, Edge, sí que lo soporta). Por lo cual, no debería haber razones para no usar las variables CSS.

Si tenéis cualquier tipo de duda podéis preguntarme sin problema.