¿Qué son las propiedades personalizadas de CSS?
Las propiedades personalizadas de CSS (lo que todo el mundo llama variables CSS) son valores que defines una vez y reutilizas por toda tu hoja de estilos. Se declaran con un prefijo de dos guiones (--) y se consultan con la función var().
``` :root { --color-primary: #0ea5e9; --spacing-base: 16px; --border-radius: 8px; }
button { background: var(--color-primary); padding: var(--spacing-base); border-radius: var(--border-radius); } ```
En qué se diferencian de las variables de Sass o Less
Las variables de un preprocesador (el $var de Sass, el @var de Less) se resuelven en la compilación, antes de que el CSS llegue al navegador. No existen en tiempo de ejecución.
- **Cambiar sobre la marcha** con JavaScript:
element.style.setProperty('--color', '#f00') - **Heredarse** por el árbol del documento, como cualquier otra propiedad CSS
- **Limitarse a un elemento** concreto en lugar de ser globales
- **Responder a las consultas de medios**, porque puedes cambiar el valor de una variable dentro de un bloque
@media
Estas capacidades las hacen más potentes que un preprocesador para los temas dinámicos.
Modo oscuro sin JavaScript
El uso más práctico de las variables CSS es el modo oscuro:
``` :root { --bg: #ffffff; --text: #0f172a; --surface: #f8fafc; }
@media (prefers-color-scheme: dark) { :root { --bg: #0f172a; --text: #f8fafc; --surface: #1e293b; } }
body { background: var(--bg); color: var(--text); } .card { background: var(--surface); } ```
Todos los elementos que usan esas variables cambian solos. Sin JavaScript, sin alternar clases y sin duplicar reglas de CSS.
Variables con alcance limitado
Las propiedades personalizadas se heredan y siguen la cascada. Una variable definida en :root es global; una definida en un componente solo afecta a ese componente y a lo que cuelga de él:
``` .alert { --alert-color: #ef4444; border: 1px solid var(--alert-color); color: var(--alert-color); }
.alert--success { --alert-color: #22c55e; } ```
La variable --alert-color cambia en .alert--success sin necesidad de declarar otra vez el borde y el color.
Valores de reserva
var() acepta un valor de reserva como segundo argumento:
var(--color-brand, #0ea5e9)
Si --color-brand no está definida, se usa #0ea5e9. Viene muy bien al crear componentes que pueden aceptar valores de tema de forma opcional.
Variables con calc()
Una de las combinaciones más potentes: espaciado adaptable sin consultas de medios.
``` :root { --fluid-space: clamp(1rem, 4vw, 3rem); }
.container { padding: var(--fluid-space); gap: calc(var(--fluid-space) / 2); } ```
Patrones habituales
**Sistema de tokens de diseño**: define todas las decisiones de espaciado, tipografía y color como variables en :root. Todo lo demás usa solo variables, nunca valores sueltos.
**Interfaz de un componente**: expón variables como --button-bg o --button-radius para que quien lo use pueda cambiarlas sin tocar la implementación interna.
**Objetivos de animación**: anima el valor de una propiedad personalizada con JavaScript y deja que las transiciones de CSS respondan solas.
**Multiplicador por punto de corte**: pon una variable --scale a 1 en móvil y a 1,25 en escritorio, y multiplica por ella todos los espaciados.
Compatibilidad con los navegadores
Las propiedades personalizadas funcionan en todos los navegadores modernos. La única excepción reseñable es Internet Explorer 11, que no las admite en absoluto. Si necesitas darle soporte, tendrás que recurrir a variables de Sass como alternativa o a un polyfill de PostCSS.