Variables CSS

Spring Boot - Spring Custom Validator

Las variables CSS o custom properties nos permiten simplificar la creación y sobre todo el mantenimiento y la reutilización de archivos CSS porque con las variables CSS podemos definir en un solo sitio los valores que de otro modo reutilizaríamos en múltiples sitios como los colores, fuentes, etc. que se suelen reutilizar en múltiples elementos y que sin la ayuda de las variables se hacía complicado de mantener ya que la única forma de hacer un cambio era buscar todas las apariciones de ese color por ejemplo y sustituirlo con la consiguiente posibilidad de cometer errores porque por ejemplo un color cómo #12df34 obviamente no te dice nada y puede ser complicado saber si es el color que estas cambiando o es una «casualidad» que sea el mismo.

Con los preprocesadores como SASS, LESS, etc. ya teníamos la posibilidad de utilizar variables pero la diferencia es que al estar soportadas nativamente en el propio CSS (y soportadas por todos los navegadores actuales desde hace un tiempo) se pueden modificar dinámicamente mediante javaScript por lo que tenemos un punto más de control sobre nuestros estilos CSS.

¿Como se definen las variables CSS?

Para definir una variable hay que poner como prefijo del nombre de la variables dos guiones ««.


:root {
  --color-texto: #fff;
}

Las variables siempre se tienen que declarar dentro de un selector CSS y son accesibles desde todos los selectores descendientes en el DOM, por eso normalmente las variables se suelen declarar usando el pseudoelemento :root que es equivalente a la etiqueta <html> para que se puedan usar de forma global.

Una cosa importante a tener en cuenta en cuanto a la definición es que no importa el orden en el que se haga la declaración y el uso de la variable porque no estamos en un lenguaje de programación como tal y por lo tanto no hay un flujo de ejecución por lo tanto sería perfectamente posible definir las variables al final de nuestros estilos.

¿Como se usan las variables CSS?

La forma de utilizar las variables es mediante var(--nombre-variable).


body {
  color: var(--color-texto);
}

La función var() opcionalmente puede tener un segundo parámetro para indicar el valor por defecto que debe de tomar en el caso de que la primera variable no este definida dentro del elemento en el que se está utilizando. Por ejemplo para que el color del texto sea azul cuando no se encuentre la variable --color-texto lo haríamos así.


.mi-clase {
  color: var(--color-texto, blue);
}

El valor por defecto no tiene por qué ser un valor fijo, se puede utilizar otra variable en su lugar para hacer definiciones de estilos más complejas en las que por ejemplo tengamos unos valores predefinidos de forma global pero queramos que si el elemento está dentro de una jerarquía determinada use los valores de está, y por supuesto nada impide que la variable que usamos como valor por defecto tenga a su vez otra variable por defecto.


.otra-clase {
  color: var(--color-texto, var(--color-texto2, var(--color-texto3, blue)));
}

Herencia de variables CSS

Aunque las llamemos variables, en realidad son unas variables un poco raras porque las «variables» CSS se heredan en los elementos hijos del elemento en el que se definen, y dentro de estos pueden redefinirse pero los cambios no afectan a la definición en el padre, por este motivo quizás les encaje mejor en nombre de propiedades personalizadas.

Vamos a verlo con un ejemplo sencillo en que tenemos un elemento padre que tiene dentro un elemento hijo y este a su vez tiene dentro otro elemento nieto.


:root {
  --color-fondo: rgb(29,30,34);
  --color-texto: #fff;
}

#padre {
  --color-fondo: #147;
  background-color: var(--color-fondo);
  padding: 10px;
}

#hijo {
  background-color: var(--color-fondo);
  width: 50%;
  padding: 5px;
  --color-fondo: #741;
  --borde: 1px solid var(--color-texto);
}

#nieto {
  background-color: var(--color-fondo);
  border: var(--borde);
  padding: 5px;
}

En este caso definimos la variable --color-fondo a nivel global, después la volvemos a redefinir en el padre y en el hijo por lo tanto esta variable tiene 3 valores distintos dependiendo de donde la utilicemos. Si la usamos en el padre el color es #147, en el hijo o en el nieto el color es #741 y si la usamos en cualquier elemento que no esté dentro del padre, el hijo o el nieto el color será rgb(29,30,34).

En este pequeño ejemplo he incluido una variable que a su vez tiene dentro otra variable para definir una propiedad con múltiples valores como el borde, esto es perfectamente válido porque nada nos impide llamar a una variable dentro de otra variable pero hay una limitación muy importante y es que en CSS no existe la posibilidad de concatenar valores y por lo tanto no podemos hacer que por ejemplo el 1 fuese una propiedad y que los px fuesen otra porque no se pueden unir.

¿Cómo acceder y modificar las variables CSS con javaScript?

Una de las cosas más interesantes que aportan las variables CSS es que se pueden editar desde el código javaScript y por lo tanto se pueden cambiar dinámicamente de forma que es posible cambiar el aspecto de varios elementos simultáneamente sin tener que tener definidas clases específicas y tener que cambiarlas una a una. Un ejemplo muy claro y muy sencillo es pensar en lo sencillo que es definir un tema usando variables para sus colores y lo simple que sería cambiar la apariencia simplemente permitiendo que el usuario los pusiese cambiar como quiera mientras puede ver sus cambios en tiempo real y además sin tener que definir ninguna clase para cada posible tema se consigue que sea 100% personalizable, aunque como con todas las cosas hay que ver cuando realmente es útil y cuando se está abusando de forma incorrecta, por ejemplo cambiar una variable desde javaScript para cambie el color al pasar por encima de un elemento es una completa estupidez, para eso esta el CSS.

La forma de acceder a una variable CSS desde javaScript es utilizando las funciones getComputedStyle() para obtener los estilos del elemento y getPropertyValue() para acceder a la propiedad concreta.


// Obtenemos una variable declarada en :root
var color = getComputedStyle(document.documentElement).getPropertyValue('--color-texto');

// Obtenemos una variable declarada en un elemento concreto
var borde = getComputedStyle(document.getElementById("nieto")).getPropertyValue('--borde');

Para poder modificar su valor necesitamos utilizar la función setProperty() sobre la propiedad style del elemento sobre el que lo queremos hacer.


function cambiarBorde() {
  document.getElementById("hijo").style.setProperty('--borde', '4px solid var(--color-otro)');
}

function cambiarFondoNieto() {
  let fondoPadre = getComputedStyle(document.getElementById("padre")).getPropertyValue('--color-fondo');
  document.getElementById("nieto").style.setProperty('--color-fondo', fondoPadre);
}

Como puedes ver en el primer ejemplo podemos darle el nuevo valor que queramos a la variable, incluida la posibilidad de usar otras variables CSS, porque al fin y al cabo desde el punto de vista de la definición es simplemente una cadena de texto que se interpretará como corresponda en el CSS, y en la segunda función redefinimos una variable en un elemento en el que inicialmente no estaba definida aunque sí que era accesible porque está definida en su padre y además le damos el valor que tiene en el nivel superior para comprobar que de verdad al redefinir una variable en un elemento hijo el cambio en la variable no afecta al padre.

Para terminar dejo el ejemplo para que puedas comprobar todo lo que hemos visto.

See the Pen
Variables CSS
by Ivan Salas (@isc7)
on CodePen.