Saltar al contenido

CSS, de a poco

Curso de CSS

Variables

Lección 22 de 37 · 3 min

Las variables de CSS le ponen nombre a un valor para usarlo en muchos lugares. Se declaran una vez, se heredan hacia abajo y se pueden pisar en cualquier parte del árbol.

Declarar y leer

Su nombre técnico es propiedad personalizada (custom property). Se declara como cualquier propiedad, pero el nombre empieza con dos guiones: --accent: oklch(0.52 0.2 290). Para leerla se usa la función var(): background: var(--accent).

  1. Distinguen mayúsculas--accent ≠ --Accent--accent y --Accent son dos variables distintas.
  2. Se heredaninheritsSi la declarás en un elemento, todos sus descendientes la pueden leer.
  3. Se leen tardevar()CSS no revisa el valor al declararla. Recién lo interpreta cuando una propiedad la lee con var().

Mové los controles y mirá cómo el botón y la tarjeta cambian juntos: los dos leen las mismas variables de .tema. Después pisá --accent en la tarjeta y quitá --radius. Las marcas naranjas muestran el valor de cada variable donde se lee: el relleno de la tarjeta, su borde y la esquina del botón.

--accent: turquesabotón: turquesa · tarjeta: turquesa

Club de lectura

Jueves 14 de noviembre, 19 h · Biblioteca Moreno

↖ radius 12px

Este mes: Los años, de Annie ErnauxQuedan 6 lugares. Vení con el libro leído hasta la página 120.

padding: var(--space) = 16px

border-color: var(--accent) = turquesa

--accent
tema.css
.tema {
--accent: oklch(0.52 0.1 190);
--radius: 12px;
--space: 16px;
}
.boton {
background: var(--accent);
color: white;
border-radius: var(--radius, 8px);
padding: calc(var(--space) / 2) var(--space);
}
.tarjeta {
border: 2px solid var(--accent);
border-radius: var(--radius, 8px);
padding: var(--space);
}
tema.html
<div class="[--accent:oklch(0.52_0.1_190)] [--radius:12px] [--space:16px]">
<button class="bg-(--accent) text-white rounded-(--radius,8px) px-(--space) py-[calc(var(--space)/2)]">Anotarme</button>
<div class="border-2 border-(--accent) rounded-(--radius,8px) p-(--space)">Este mes: Los años, de Annie Ernaux</div>
</div>

Alcance y cascada

Una variable vive en el elemento que la declara y en sus descendientes. Sigue la cascada normal: especificidad, orden y herencia, igual que color. Por eso declararla en .tarjeta cambia el acento solo dentro de la tarjeta, y el botón sigue con el de .tema.

El segundo argumento de var() es el valor de respaldo (fallback). Con var(--radius, 8px), si --radius no está definida en ningún ancestro, se usan 8px. Es lo que pasa en la demo al quitarla.

tarjeta.css
.tema {
--space: red; /* válido: no se revisa al declarar */
}
.tarjeta {
padding: 24px;
padding: var(--space); /* inválido al calcularse: queda en 0 */
}

Ojo con ese caso: si la variable existe pero su valor no sirve para la propiedad, la declaración es inválida al calcular el valor (invalid at computed-value time). No se usa el respaldo ni el padding: 24px anterior; la propiedad se comporta como unset, y como padding no se hereda, vale 0.

Dos tarjetas con padding: 24px y después padding: var(--space). Con --space: 16px la tarjeta tiene 16px de relleno; con --space: red la declaración es inválida y el relleno queda en 0, con el texto pegado al borde.

Usos prácticos

  1. Tokens de diseño:rootColores, radios y espacios con nombre en :root, para cambiarlos en un solo lugar.
  2. Temasprefers-color-schemeRedefinís los mismos tokens dentro de @media (prefers-color-scheme: dark) y todo lo que los lee cambia. Este sitio lo hace así.
  3. Cálculoscalc(var(--space) * 2)Con --space: 16px da 32px. Para sumar una unidad a un número usá calc(var(--n) * 1px); var(--n)px no funciona.
tema.css
:root {
--bg: oklch(0.99 0 0);
--text: oklch(0.2 0 0);
}
@media (prefers-color-scheme: dark) {
:root {
--bg: oklch(0.2 0 0);
--text: oklch(0.95 0 0);
}
}
body {
background: var(--bg);
color: var(--text);
}

Una variable común no tiene tipo, así que el navegador no sabe interpolarla y una transición sobre ella salta de golpe. Con @property la registrás con un tipo (syntax), si se hereda (inherits) y un valor inicial (initial-value). Así se puede animar:

Una flecha que gira de 0 a 90 grados. Sin @property salta de una posición a la otra; con @property pasa por todos los ángulos intermedios en 300ms.
flecha.css
@property --angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.flecha {
transform: rotate(var(--angle));
transition: --angle 300ms;
}
.flecha:hover {
--angle: 90deg;
}

En Tailwind

En Tailwind v4 los valores del tema ya son variables: --spacing o --color-white viven en :root. Para declarar una propia en un elemento se usa una propiedad arbitraria entre corchetes, y para leerla, la clase con el nombre entre paréntesis.

CSSTailwind
--space: 16px[--space:16px]
background-color: var(--accent)bg-(--accent)
border-color: var(--accent)border-(--accent)
padding: var(--space)p-(--space)
border-radius: var(--radius, 8px)rounded-(--radius,8px)
--color-accent en @themebg-accent · border-accent
tema.html
<div class="[--accent:oklch(0.52_0.2_290)] [--space:16px]">
<button class="bg-(--accent) text-white rounded-(--radius,8px)
px-(--space) py-[calc(var(--space)/2)]">
Guardar
</button>
<div class="[--accent:oklch(0.52_0.2_10)]
border-2 border-(--accent) p-(--space)">
Tarjeta
</div>
</div>