Variables de CSS: ¿Por qué debería importarte?

Las variables de CSS, conocidas como propiedades personalizadas de CSS, están llegando a Chrome 49. Pueden ser útiles para reducir la repetición en CSS. también para potentes efectos de tiempo de ejecución, como el cambio de tema y la posible la extensión o el polyfilling de futuras funciones de CSS.

Desorden de CSS

Cuando se diseña una aplicación, es una práctica común separar un conjunto de colores que se reutilizarán para mantener la apariencia de la app coherente. Lamentablemente, repetir estos valores de color una y otra vez en tu CSS es no solo una tarea tediosa, sino también propensa a errores. Si, en algún momento, uno de los colores se deba cambiar, podrías echarle cautela al viento y "buscar y reemplazar" pero en un proyecto lo suficientemente grande podría ser peligroso.

Recientemente, muchos desarrolladores recurrieron a preprocesadores de CSS, como SASS o MENOS que resuelven este problema mediante el uso de variables del preprocesador. Mientras que estas herramientas han aumentado significativamente la productividad de los desarrolladores, las variables que que usan tienen un gran inconveniente, que es que son estáticos y no se pueden cambian en el tiempo de ejecución. Agregar la habilidad de cambiar variables en el entorno de ejecución no solo abre la puerta a aspectos como los temas dinámicos de las aplicaciones, pero también las consecuencias para el diseño responsivo y el potencial de polyfill en el futuro de CSS atributos. Con el lanzamiento de Chrome 49, estas capacidades ya están disponibles en las propiedades personalizadas de CSS.

Resumen de las propiedades personalizadas

Las propiedades personalizadas agregan dos funciones nuevas a nuestra caja de herramientas de CSS:

  • La capacidad de un autor de asignar valores arbitrarios a una propiedad con una nombre elegido por el autor.
  • La función var(), que permite que un autor use estos valores en otros propiedades.

Aquí hay un ejemplo rápido para demostrar

:root {
    --main-color: #06c;
}

#foo h1 {
    color: var(--main-color);
}

--main-color es una propiedad personalizada definida por el autor con un valor de #06c. Nota que todas las propiedades personalizadas comiencen con dos guiones.

La función var() se recupera y se reemplaza por la propiedad personalizada. , lo que da como resultado color: #06c;, siempre que la propiedad personalizada esté definida en alguna parte de la hoja de estilo, debería estar disponible para la función var.

Al principio, la sintaxis puede parecer un poco extraña. Muchos desarrolladores preguntan: solo usar $foo para los nombres de las variables?" El enfoque se eligió específicamente lo más flexible posible y, posiblemente, permitir macros de $foo en el futuro. Para obtener información de fondo, puedes leer esta publicación. de uno de los autores de las especificaciones, Tab Atkins.

Sintaxis de propiedades personalizadas

La sintaxis de una propiedad personalizada es sencilla.

--header-color: #06c;

Ten en cuenta que las propiedades personalizadas distinguen mayúsculas de minúsculas, por lo que --header-color y --Header-Color son propiedades personalizadas diferentes. Si bien pueden parecer simples nominal, la sintaxis permitida para las propiedades personalizadas es bastante permisivo. Por ejemplo, la siguiente es una propiedad personalizada válida:

--foo: if(x > 5) this.width = 10;

Si bien no sería útil como variable, ya no sería válido en cualquier propiedad normal, se podría leer y responder con JavaScript en tiempo de ejecución. Esto significa que las propiedades personalizadas pueden desbloquear todo tipo de técnicas interesantes que actualmente no son posibles con los preprocesadores de CSS actuales. De esta manera, si estás pensando “bostezo, tengo SASS y a quién le importa...”, vuelve a mirar el contenido. Estas no son las variables con las que estás acostumbrado a trabajar.

La cascada

Las propiedades personalizadas siguen reglas de cascada estándar, por lo que puedes definir propiedad con diferentes niveles de especificidad

:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
<p>I inherited blue from the root element!</p>
<div>I got green set directly on me!</div>
<div id="alert">
    While I got red set directly on me!
    <p>I’m red too, because of inheritance!</p>
</div>

Esto significa que puedes aprovechar las propiedades personalizadas en las consultas de medios para ayudar con el diseño adaptable. Un caso de uso podría ser ampliar los márgenes los elementos principales de seccionamiento a medida que aumenta el tamaño de la pantalla:

:root {
    --gutter: 4px;
}

section {
    margin: var(--gutter);
}

@media (min-width: 600px) {
    :root {
    --gutter: 16px;
    }
}

Es importante señalar que el fragmento de código anterior no es posible mediante preprocesadores de CSS actuales, que no pueden definir variables en medios para tus consultas. Con esta habilidad se desbloquea un gran potencial.

También es posible tener propiedades personalizadas que deriven su valor de otras propiedades personalizadas. Esto puede ser muy útil para la creación de temas:

:root {
    --primary-color: red;
    --logo-text: var(--primary-color);
}

La función var()

Para recuperar y usar el valor de una propiedad personalizada, deberás usar el función var(). La sintaxis de la función var() se ve de la siguiente manera:

var(<custom-property-name> [, <declaration-value> ]? )

Donde <custom-property-name> es el nombre de una propiedad personalizada definida por el autor. como --foo, y <declaration-value> es un valor de resguardo que se usará cuando la propiedad personalizada referenciada no es válida. Los valores de resguardo pueden estar separados por comas que se combinará en un solo valor. Por ejemplo, var(--font-stack, "Roboto", "Helvetica"); define un resguardo de "Roboto", "Helvetica". Conservar en tenga en cuenta que los valores abreviados, como los que se usan para el margen y el relleno, separados por comas, de modo que un resguardo apropiado para el relleno se vería de la siguiente manera:

p {
    padding: var(--pad, 10px 15px 20px);
}

Con estos valores de resguardo, el autor de un componente puede escribir estilos defensivos para su elemento:

/* In the component’s style: */
.component .header {
    color: var(--header-color, blue);
}
.component .text {
    color: var(--text-color, black);
}

/* In the larger application’s style: */
.component {
    --text-color: #080;
    /* header-color isn’t set,
        and so remains blue,
        the fallback value */
}

Esta técnica es especialmente útil para aplicar temas a componentes web que usan Shadow DOM, ya que las propiedades personalizadas pueden atravesar límites de sombras. Autor de un componente web puede crear un diseño inicial con valores de resguardo y exponer “hooks” de temas en forma de propiedades personalizadas.

<!-- In the web component's definition: -->
<x-foo>
    #shadow
    <style>
        p {
        background-color: var(--text-background, blue);
        }
    </style>
    <p>
        This text has a yellow background because the document styled me! Otherwise it
        would be blue.
    </p>
</x-foo>
/* In the larger application's style: */
x-foo {
    --text-background: yellow;
}

Cuando usas var(), debes tener en cuenta algunos problemas. Las variables no pueden los nombres de las propiedades. Por ejemplo:

.foo {
    --side: margin-top;
    var(--side): 20px;
}

Sin embargo, esto no equivale a configurar margin-top: 20px;. En cambio, el La segunda declaración no es válida y se descarta como un error.

Del mismo modo, no puede (ingenir) crear un valor si parte de él lo proporciona una variable:

.foo {
    --gap: 20;
    margin-top: var(--gap)px;
}

Nuevamente, esto no equivale a configurar margin-top: 20px;. Para crear un valor, necesitas algo más: la función calc().

Cómo compilar valores con calc()

Si nunca trabajaste con ella, la función calc() es un poco que te permite realizar cálculos para determinar los valores de CSS. Es compatible con todos los navegadores modernos y se puede combinar. con propiedades personalizadas para crear valores nuevos. Por ejemplo:

.foo {
    --gap: 20;
    margin-top: calc(var(--gap) * 1px); /* niiiiice */
}

Cómo trabajar con propiedades personalizadas en JavaScript

Para obtener el valor de una propiedad personalizada en el tiempo de ejecución, usa getPropertyValue(). del objeto CSSStyleDeclaration calculado.

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>I’m a red paragraph!</p>
/* JS */
var styles = getComputedStyle(document.documentElement);
var value = String(styles.getPropertyValue('--primary-color')).trim();
// value = 'red'

De forma similar, para configurar el valor de una propiedad personalizada en el tiempo de ejecución, usa la Método setProperty() del objeto CSSStyleDeclaration

/* CSS */
:root {
    --primary-color: red;
}

p {
    color: var(--primary-color);
}
<!-- HTML -->
<p>Now I’m a green paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'green');

También puedes configurar el valor de la propiedad personalizada para hacer referencia a otra. en el entorno de ejecución con la función var() en tu llamada a setProperty()

/* CSS */
:root {
    --primary-color: red;
    --secondary-color: blue;
}
<!-- HTML -->
<p>Sweet! I’m a blue paragraph!</p>
/* JS */
document.documentElement.style.setProperty('--primary-color', 'var(--secondary-color)');

Debido a que las propiedades personalizadas pueden hacer referencia a otras propiedades personalizadas en tu hojas de estilo, puedes imaginarte cómo esto podría dar lugar a todo tipo de los efectos del tiempo de ejecución.

Navegadores compatibles

Actualmente, Chrome 49, Firefox 42, Safari 9.1 y Safari 9.3 de iOS admiten propiedades.

Demostración

Prueba la muestra para tener una idea de todas las técnicas interesantes que puedes aprovechar ahora. en propiedades personalizadas.

Lecturas adicionales

Si quieres obtener más información sobre las propiedades personalizadas, el equipo de Google Analytics escribió una guía sobre por qué le entusiasman las propiedades personalizadas. y puedes consultar su progreso en otros navegadores en chromestatus.com.