En esta página
Custom properties (variables CSS)
Qué son las custom properties?
Las custom properties (también llamadas variables CSS) son valores reutilizables que defines con -- y consumes con var(). A diferencia de las variables de Sass o Less, las custom properties son nativas del navegador, funcionan en tiempo de ejecución y participan en la cascada.
:root {
--mi-color: #ff5500;
}
.elemento {
color: var(--mi-color);
}Definir variables
Las variables se definen dentro de cualquier selector CSS. La convención es definir las globales en :root:
:root {
--color-primario: oklch(65% 0.2 25);
--espaciado: 1rem;
--font-base: system-ui, sans-serif;
}Scope: cascada y herencia
Las custom properties heredan a los hijos, como color o font-family. Esto significa que puedes redefinir una variable en un contenedor y todos sus hijos la usaran:
:root { --bg: white; }
.sección-oscura {
--bg: #1a1a2e; /* Solo dentro de esta sección */
}
.card {
background: var(--bg); /* Hereda del contexto */
}Consumir variables con var()
La función var() acepta dos argumentos: la variable y un valor de respaldo opcional:
.elemento {
color: var(--mi-color, #333);
/* Si --mi-color no existe, usa #333 */
}Los fallbacks pueden ser otros var():
color: var(--color-tema, var(--color-base, black));Variables de componente
Un patrón poderoso es definir variables privadas dentro de un componente y sobreescribirlas con modificadores:
.boton {
--btn-bg: #1a1a2e;
--btn-text: white;
--btn-radius: 8px;
background: var(--btn-bg);
color: var(--btn-text);
border-radius: var(--btn-radius);
padding: 0.75rem 1.5rem;
}
.boton--primario { --btn-bg: #ff530f; }
.boton--secundario { --btn-bg: transparent; --btn-text: #1a1a2e; }
.boton--pill { --btn-radius: 999px; }Temas con custom properties
La mayor ventaja de las custom properties es la tematizacion. Defines los tokens una vez y los cambias segun el contexto:
:root {
--bg: white;
--text: #1a1a2e;
--border: #e0e0e0;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #0a0a0f;
--text: #e8e8e8;
--border: rgb(255 255 255 / 10%);
}
}
/* También puedes tener temas por clase */
[data-theme="alto-contraste"] {
--bg: black;
--text: white;
--border: white;
}Variables dinamicas desde HTML
Puedes pasar variables desde el HTML con style inline. Esto es útil para valores que vienen de JavaScript o datos dinámicos:
<div class="progreso" style="--valor: 75%"></div>.progreso::after {
width: var(--valor, 0%);
}Variables con calc() y otras funciones
Las custom properties se pueden usar dentro de funciones CSS:
:root {
--base: 1rem;
}
.grande {
font-size: calc(var(--base) * 2); /* 2rem */
padding: calc(var(--base) * 0.5); /* 0.5rem */
}Custom properties vs preprocesadores
| Caracteristica | Custom properties | Sass/Less |
|---|---|---|
| Ejecución | Navegador (runtime) | Compilacion (build) |
| Cascada | Si | No |
| Temas dinámicos | Si | No (sin JS) |
| Media queries | Se pueden redefinir | No |
| JavaScript | Accesibles | No |
Las custom properties no reemplazan completamente a los preprocesadores (que ofrecen loops, mixins, funciones), pero para tematizacion y valores dinámicos son superiores.
@property: variables tipadas
Con @property puedes registrar una custom property con tipo, valor inicial y comportamiento de herencia:
@property --progreso {
syntax: "<percentage>";
inherits: false;
initial-value: 0%;
}
.barra {
--progreso: 0%;
background: linear-gradient(to right, #b056ff var(--progreso), #e0e0e0 0);
transition: --progreso 500ms ease; /* Ahora se puede animar */
}
.barra:hover {
--progreso: 100%;
}Sin @property, las custom properties no se pueden animar con transiciones porque el navegador no conoce su tipo.
Las custom properties son la base del CSS mantenible. En la siguiente leccion exploraremos las funcionalidades más recientes de CSS en 2026.
Práctica
- Define un sistema de tokens: Crea variables globales en
:rootpara colores, espaciado y border-radius. Usa esas variables en al menos 3 componentes diferentes (boton, tarjeta, badge). - Crea variantes con variables de componente: Construye un componente
.botoncon variables internas (--btn-bg,--btn-text) y crea modificadores (.boton--primario,.boton--secundario) que solo redefinan las variables. - Anima una custom property con @property: Registra una variable
--progresocon@property, aplicala a un gradiente lineal y animala contransitional hacer hover.
/* Definir variables globales */
:root {
--color-brand: oklch(75% 0.18 85);
--color-accent: oklch(55% 0.22 340);
--color-text: oklch(15% 0.01 260);
--color-surface: oklch(98% 0.005 260);
--font-sans: system-ui, sans-serif;
--font-mono: "Fira Code", monospace;
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 16px;
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 2rem;
--space-xl: 4rem;
}
/* Tema oscuro: solo redefinir variables */
@media (prefers-color-scheme: dark) {
:root {
--color-text: oklch(92% 0.01 260);
--color-surface: oklch(12% 0.01 260);
}
}
/* Uso en componentes */
.card {
background: var(--color-surface);
color: var(--color-text);
border-radius: var(--radius-lg);
padding: var(--space-lg);
font-family: var(--font-sans);
}
.boton {
background: var(--color-brand);
padding: var(--space-sm) var(--space-md);
border-radius: var(--radius-md);
border: none;
cursor: pointer;
}
/* Variables de componente con scope local */
.badge {
--badge-bg: #e0e0e0;
--badge-text: #333;
--badge-size: 0.75rem;
background: var(--badge-bg);
color: var(--badge-text);
font-size: var(--badge-size);
padding: 0.25em 0.75em;
border-radius: 999px;
display: inline-block;
}
/* Variantes: solo redefinir las variables */
.badge--éxito {
--badge-bg: oklch(85% 0.15 145);
--badge-text: oklch(25% 0.1 145);
}
.badge--error {
--badge-bg: oklch(85% 0.12 25);
--badge-text: oklch(30% 0.15 25);
}
.badge--grande {
--badge-size: 1rem;
}
/* Variables desde HTML (inline) */
.barra-progreso {
height: 8px;
background: #e0e0e0;
border-radius: 4px;
overflow: hidden;
}
.barra-progreso::after {
content: "";
display: block;
height: 100%;
width: var(--progreso, 0%);
background: var(--color-brand, #b056ff);
border-radius: 4px;
transition: width 500ms ease;
}
Inicia sesión para guardar tu progreso