Variables CSS

CSS Custom Properties: Variables nativas de CSS


Quizás lo desconozcas, ya que es una característica que no estaba presente en las primeras versiones de CSS, pero existe una forma nativa de guardar valores a través de «variables CSS». Estas variables CSS no existían hace años, y de hecho, fue una de las razones por las que se popularizaron preprocesadores como LESS o Sass, que sí las incorporaban.

CSS Custom Properties - Variables CSS

Sin embargo, las frecuentemente denominadas variables CSS realmente no son variables, sino que solemos denominarlas así por su parecido con la programación y porque es más fácil comprender rápidamente lo que son, pero tienen sus diferencias. La forma oficial de llamarlas es custom properties (propiedades personalizadas).

CSS Custom Properties

Las CSS Custom Properties (conocidas como variables CSS) son un mecanismo de CSS que permite dar un valor personalizado a las propiedades CSS. El objetivo principal es evitar escribir múltiples veces un mismo valor, y en su lugar, ponerle un nombre más lógico, semántico y fácil de recordar, que hará referencia al valor real. De esta forma será mucho más legible y más fácil de mantener.

También recuerda que no se trata de usar variables CSS en cualquier situación, sino sólo para aquellos valores sensibles a ser reutilizados, modificados o donde queramos dar semántica extra mediante estas custom properties.

Las custom properties tienen un buen soporte en navegadores en la actualidad:

Definir o crear variables CSS

Para crear una custom property haremos uso de los dos guiones -- como prefijo al nombre que vamos a utilizar. En este caso, hemos creado una variable CSS llamada --background-color, al que le hemos asignado el valor black, que es un color:

:root {
  --background-color: black;
}

Observa que en este caso, hemos establecido la variable dentro del selector con pseudoclase :root. Esta pseudoclase :root hace referencia al elemento raíz del documento, es decir, al elemento <html>. La diferencia entre utilizar html o :root como selector es que este último tiene algo más de especificidad CSS. Mientras el selector html tiene (0,0,1), :root tendría (0,1,0).

De esta forma estamos estableciendo lo que se suele conocer como una variable global, es decir, una variable que está disponible para utilizar en cualquier parte del documento. Más adelante veremos que no es la única forma.

Las custom properties se suelen agrupar en las primeras líneas de un bloque CSS, separándolas por una línea en blanco de las demás propiedades. Esto facilita la lectura del código.

Utilizar una variable CSS

A la hora de utilizar una custom property, hay que utilizar la función var(), indicando el nombre de la variable. Observa este sencillo ejemplo:

:root {
  --background-color: indigo;
}

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

En este caso estamos aplicando a la propiedad background el valor que contiene la variable --background-color en el elemento <body>. Observa que aunque la variable fue definida en :root, o sea en la etiqueta <html>, existe en todos sus elementos hijos, por lo que también existe en <body> y se puede utilizar.

Fallback en variables CSS

Además, en muchas situaciones es recomendable que la función var() tenga dos parámetros. El primer parámetro es la variable en cuestión, pero el segundo parámetro opcional es el valor por defecto, que se utilizará en el caso de que esa variable no esté definida:

body {
  background: var(--background-color, green);
}

En este caso, la variable --background-color no está definida, por lo que el elemento <body> tendrá el color de fondo verde, ya que es el fallback indicado.

Ten en cuenta que en lugar de green podríamos indicar otra variable CSS diferente mediante la función var(). De esta forma, estaríamos definiendo una variable a partir de otra, algo que podría ser útil si tenemos una lista de variables CSS predefinidas, como hace Open Props.

Ámbito de las custom properties

El ejemplo anterior es muy sencillo, y en él hemos definido una variable de forma global, disponible para todo el documento. Sin embargo, es importante saber que las variables CSS tienen ámbito o «scope», por lo que se pueden definir en un ámbito local.

Observa el código HTML del siguiente ejemplo, donde tenemos tres elementos con clase child:

<div class="parent">
  <div class="first child">First child</div>
  <div class="second child">Second child</div>
  <div class="third child">Third child</div>
</div>
.parent {
  --background-color: black;

  background: indigo;
  padding: 1rem;
  display: flex;
  gap: 1rem;
}

.child {
  width: 100px;
  height: 100px;
  background: var(--background-color);
}

.first {
  --background-color: gold;
}
  • 1️⃣ En la clase .parent definimos una variable --background-color a black. Para ese elemento y todos sus hijos, existe esa variable. Fuera de .parent, no existe.
  • 2️⃣ En la clase .child usamos la variable, por lo tanto pintaremos los 3 elementos.
  • 3️⃣ En la clase .first redefinimos la variable con el color gold.

Como resultado, tenemos tres cuadrados, uno gold y dos black. Esto ocurre así porque en .first redeclaramos la variable, asignándole un nuevo valor que sólo existe en ese elemento con clase .first.

Esto nos permite mucha flexibilidad y potencia a la hora de utilizar custom properties en CSS, ya que son tremendamente útiles y versátiles, permitiéndonos utilizar incluso la cascada de CSS a nuestro favor:

<div class="card love-type">
  <div class="frame">
    <h2>ManzDev</h2>
    <img src="manzdev-love.gif" alt="ManzDev">
  </div>
</div>
.love-type {
  --color: darkred;
}

.card {
  max-width: 250px;
  border: 6px solid black;
  padding: 1rem;
  box-shadow: 6px 6px 10px #000a;
  background: linear-gradient(black, var(--color));

  & .frame {
    border: 6px solid var(--color);
    background: white;
    display: grid;
    place-items: center;
  }

  & h2 {
    text-align: center;
    background: var(--color);
    color: white;
    padding: 0 0.75rem;
  }

  & img {
    width: 90%;
  }
}

Como se puede ver en este ejemplo, hemos utilizado la clase .love-type para definir la variable, y hemos reutilizado la variable a lo largo del componente .card, utilizándolo en varias partes de la misma.

Diferencia con Sass

Es importante mencionar que las variables CSS no funcionan exactamente igual que las variables Sass (o en general, las variables de preprocesadores). Sass, al igual que muchos otros preprocesadores de CSS, no trabajan directamente en el navegador, sino en una «fase» previa (fase de preprocesamiento).

Es el caso de las variables de Sass, dichas variables son leídas por Sass y convertidas a CSS «plano» (sin variables) antes de ser leído por el navegador:

/* Código Sass (las variables se definen en el top) */
$var: #fff;

.parent {
  background: $var;
}

.parent .element {
  $var: #888;
}

.element {
  background: $var;
}
/* El código Sass anterior es equivalente a este código CSS */
.parent {
  background: #fff;
}

.element {
  background: #fff;
}

Es por eso que no deben tomarse las custom properties como equivalente de las variables SCSS, que aunque son muy parecidas, tienen matices diferentes.

Variables CSS desde Javascript

Existen varias formas de manipular estilos CSS desde Javascript:

  • 1️⃣ Mediante propiedades del objeto .style
  • 2️⃣ Mediante la función global .getComputedStyle()
  • 3️⃣ Mediante el método .setProperty() del objeto .style

En esta ocasión nos centraremos en el último método, ya que nos permite modificar las propiedades CSS (y variables CSS) de un elemento de forma muy sencilla. Observen el siguiente ejemplo:

<div class="first">Primer mensaje de texto.</div>
<div class="second">Segundo mensaje de texto.</div>
const firstElement = document.querySelector(".first");
firstElement.style.setProperty("border", "2px solid red");

Al igual que hemos modificado la propiedad border en este caso, podríamos hacer lo mismo con una custom property. En ambos casos, quedarían añadidas en el atributo HTML style del elemento, afectando a ese elemento concreto (y a sus elementos descendientes).

Los métodos derivados de .setProperty() son los siguientes:

Método Descripción
.setProperty(propName, value, priority) Añade o cambia el valor de una propiedad o variable CSS.
.getPropertyValue(propName) Obtiene el valor de una propiedad o variable CSS.
.getPropertyPriority(propName) Devuelve important si tiene prioridad.
.removeProperty(propName) Elimina una propiedad o variable CSS de un elemento.

El método que hemos visto anteriormente es .style.setProperty(), con el cuál podemos añadir (o modificar) un valor a una propiedad. Además, si establecemos el tercer parámetro con el "important", sería el equivalente a añadirle el !important al valor de la propiedad.

Por otro lado, tenemos el método opuesto .style.getPropertyValue() mediante el cuál podemos obtener el valor de una propiedad concreta o el método .style.getPropertyPriority(), con el cuál te devuelve el string important si lo tiene definido. Por último, el método .style.removeProperty() como su propio nombre indica, elimina una propiedad de un elemento.

Ten en cuenta que estos métodos solo funcionan si las propiedades o variables CSS han sido definidas en el atributo style de CSS (o con estos mismos métodos).

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev