Propiedades CSS con valores predeterminados
En 2021, Lea Verou compartió un patrón brillante para manejar valores predeterminados en variables CSS. Ahora, en 2026, aunque ese patrón sigue siendo útil, también tenemos la poderosa regla @property como una característica estándar. Veamos las formas “Clásica” y “Moderna” de manejar los valores predeterminados de los componentes.
La Forma “Clásica”: El Patrón --_
Esta técnica resuelve los problemas de especificidad utilizando una variable interna “privada”.
El Problema
Si definimos el estilo de un componente usando una variable con un fallback en múltiples lugares:
.button {
background: var(--bg, black);
border-color: var(--bg, black);
}
Estamos repitiendo var(--bg, black). Si queremos cambiar el valor predeterminado a blue, tenemos que editarlo en todas partes.
La Solución: Variables Pseudo-Privadas
Creamos una nueva variable, con el prefijo _ (guion bajo), que actúa como nuestra fuente de verdad interna.
.button {
/* Variable interna = Variable pública O Predeterminado */
--_bg: var(--bg, black);
/* Usamos la variable interna en todas partes */
background: var(--_bg);
border: 1px solid var(--_bg);
}
Para personalizarlo, el usuario simplemente configura la variable pública:
.button.red {
--bg: red;
}
Esto actúa como un Constructor para tu componente CSS. Es ligero, no requiere registro global y funciona perfectamente para el alcance local.
La Forma “Moderna”: usando @property
Con el soporte generalizado de @property, ahora podemos definir variables que realmente tienen valores predeterminados, tipos e incluso son animables.
En lugar de necesitar una variable intermedia “privada”, registramos la propiedad pública directamente.
@property --button-bg {
syntax: "<color>";
initial-value: black;
inherits: true;
}
.button {
/* No es necesario var(--button-bg, black) - ¡el fallback es nativo! */
background: var(--button-bg);
border: 1px solid var(--button-bg);
/* Plus: ¡Ahora podemos transicionar esta variable! */
transition: --button-bg 0.3s;
}
¿Por qué usar @property?
- Seguridad de Tipos: El navegador sabe que
--button-bges un<color>. Si alguien configura--button-bg: 20px, es inválido y vuelve ablack(el valor inicial), en lugar de romper la UI. - Animación: Puedes hacer una transición de
blackaredsuavemente porque el navegador sabe cómo interpolar colores. Las variables estándar saltan de un valor a otro. - Código más limpio: No hay necesidad del truco
--_si estás de acuerdo con el registro global.
¿Cuál elegir?
-
Usa el patrón
--_para componentes locales simples donde no quieres contaminar el espacio de nombres global con propiedades registradas o cuando necesitas valores predeterminados “suaves” que cambien según el contexto. -
Usa
@propertycuando necesites animación, tipos estrictamente aplicados o estés construyendo un Sistema de Diseño robusto donde las propiedades estén bien documentadas y sean globalmente únicas.
Mi Recomendación: La Configuración Profesional
Para llevar tu arquitectura CSS al siguiente nivel, recomiendo combinar estos patrones con una configuración base sólida:
- Variables Globales en
:root: Define tus design tokens (colores, unidades de espaciado, escala) en un archivo base con scope:root. - Organiza con
@layer: Recomiendo encarecidamente usar la regla@layerpara gestionar la cascada de CSS. Ahora que tiene el estatus de Baseline Widely available, es la mejor forma de manejar el contexto y los overrides, especialmente en plataformas o frameworks que inyectan estilos a muchos niveles. Puedes leer más en mi post: Organiza Estilos en CSS con @layer Eficazmente. - Espaciado y Tamaños Consistentes: Usa una unidad base
--spacingy calcula tus paddings y margins a partir de ella (ej.padding: calc(var(--spacing) * 4)). Esto garantiza una armonía visual en todo el proyecto. - Tipografía Fluida con
clamp(): No uses tamaños de fuente estáticos. Usaclamp()para crear una tipografía fluida que escale perfectamente entre móvil y escritorio sin necesidad de docenas de media queries.
/* 1. Configuración Global con @layer y tokens en :root */
@layer tokens, base, components;
@layer tokens {
:root {
--spacing: 0.25rem;
/* 2. Tipografía Fluida con clamp() */
--font-size-base: clamp(1rem, 1.2vw, 1.125rem);
--color-primary: #3b82f6;
--color-text: #1f2937;
}
}
@layer components {
.card {
/* 3. Variables pseudo-privadas para la lógica del componente */
--_bg: var(--card-bg, #ffffff);
/* 4. Espaciado consistente usando calc() */
--_padding: calc(var(--spacing) * 6);
background: var(--_bg);
padding: var(--_padding);
font-size: var(--font-size-base);
color: var(--color-text);
border: 1px solid var(--color-primary);
border-radius: calc(var(--spacing) * 2);
/* Habilitar transición para la propiedad personalizada */
transition: --card-bg 0.3s ease;
}
}
/* 5. @property registrada para transiciones suaves */
@property --card-bg {
syntax: "<color>";
initial-value: #ffffff;
inherits: false;
}
.card:hover {
--card-bg: #f3f4f6;
}
Al combinar el patrón --_ de Lea para componentes con un sistema global en :root, obtienes lo mejor de ambos mundos: consistencia global y flexibilidad local. ¡De hecho, utilicé exactamente esta arquitectura para construir este sitio web!
Actualizado para 2026. Basado en Custom properties with defaults: 3+1 strategies




Comments for LVCSTP