Temas y propiedades personalizadas de CSS | Programar Plus

Hace poco publicamos sobre la diferencia entre las variables CSS nativas (propiedades personalizadas) y las variables del preprocesador. Hay algunas cosas esotéricas que las variables de preprocesador pueden hacer que las variables nativas no pueden, pero en su mayor parte, las variables nativas pueden hacer las mismas cosas. Pero son más poderosos debido a cómo se interpolan en vivo. Si sus valores alguna vez cambian (por ejemplo, JavaScript, consultas de medios, etc.), el cambio desencadena un cambio inmediato en el sitio.

¿Guay, verdad? Pero aún así, ¿qué tan útil es eso? ¿Cuáles son los principales casos de uso? Creo que todavía estamos viendo cómo se agitan.

Se me ocurrió que un caso de uso sería la tematización de un sitio (piense: colores personalizados para elementos alrededor de un sitio). En lugar de escribir CSS diferente para un montón de temas diferentes, o escribir JavaScript que se dirija a todos los elementos que pretendemos cambiar y cambiarlos), simplemente escribimos un conjunto base de CSS que utiliza variables y establecemos esas variables en los colores del tema.

Imagine que permitimos que se personalice el fondo del encabezado y pie de página de nuestro sitio.

header {
  background: var(--mainColor);
}

...

footer {
  background: var(--mainColor);
}

Quizás haya un subtítulo con una variación más oscura de ese color. Aquí hay un pequeño truco para colocar una capa transparente de color sobre otra:

.subheader {
  background: 
    /* Make a bit darker */
    linear-gradient(
      to top,
      rgba(0, 0, 0, 0.25),
      rgba(0, 0, 0, 0.25)
    )
    var(--mainColor);
}

Donde hace --mainColor ¿viene de?

Con la tematización, la idea es que se la pidas al usuario. Afortunadamente tenemos entradas de color:

<input type="color">

Y puede almacenar ese valor en una base de datos o en cualquier otro mecanismo de almacenamiento que desee. Aquí hay una pequeña demostración donde el valor se almacena en localStorage:

El valor se saca de localStorage y se utiliza cuando se carga la página. También se establece un valor predeterminado (en CSS), en caso de que no exista.

Lo que hace que la demostración anterior sea tan atractiva, para mí, es lo poco que es el código. Mantener esto como una característica en un sitio es en gran parte un esfuerzo de CSS y parece lo suficientemente flexible como para resistir la prueba del tiempo (probablemente).

No es raro que estuviera muy atrasado en esto.

Mucha gente piensa en la tematización como uno de los principales casos de uso de las propiedades personalizadas de CSS. Veamos algunos ejemplos de otras personas.

Giacomo Zinetti tiene el mismo tipo de implementación de selector de color

En su sitio:

Ejemplos y consejos de Harry Roberts

Escribió “Tematización pragmática, práctica y progresiva con propiedades personalizadas”, en la que señaló aplicaciones como Twitter y Trello que ofrecen tematización directamente a los usuarios:

Harry realiza muchas consultorías y, para mi sorpresa, se encuentra trabajando con empresas que quieren hacer mucho esto. El Advierte:

La temática, la gran mayoría de las veces, es completamente agradable de tener. No es crítico para el negocio o, por lo general, ni siquiera importante. Si se le solicita que proporcione dicha temática, no lo haga a expensas del rendimiento o la calidad del código.

In Sass / In React

En una aplicación de tematización en el mundo real a través de Propiedades personalizadas, Dan Bahrami relata cómo lo hicieron en Geckoboard, el producto en el que trabaja:

Es un producto de React, pero no usan ningún estilo en JavaScript, por lo que optaron por tematizar con Propiedades personalizadas, a través de Sass.

@mixin variable($property, $variable, $fallback) {
  #{$property}: $fallback;
  #{$property}: var($variable);
}

Entonces ellos pueden hacer:

.dashboard {
  @include variable(background, --theme-primary-color, blue);
}

Que se compila para tener un respaldo:

.dashboard {
  background: blue;
  background: var(--theme-primary-color);
}

También crearon react-custom-properties que tratan sobre la aplicación de propiedades personalizadas a los componentes, aprovechando el hecho de que puede establecer propiedades personalizadas como estilos en línea:

<div style="--theme-primary-color: blue;">

</div>

Más de un color y propiedad

No solo los colores pueden cambiar, una propiedad personalizada puede ser cualquier valor válido. Aquí está Keith Clark con una demostración con varios colores y tamaño de fuente:

Y David Darnes con la temática incorporada en un sitio de Jekyll:

Demostración de Microsoft

Greg Whitworth creó esta demostración (ahora sin conexión, lo siento):

Que utiliza modificadores de color dentro de las propias funciones de color:

.distant-building__window {
  fill: rgb(
    calc(111 + (111 * var(--building-r-mod))),
    calc(79 + (79 * var(--building-g-mod))),
    calc(85 + (85 * var(--building-b-mod)))
  );
}

Lo cual no es compatible con todos los navegadores.

Greg también señaló que las funciones de color CSS4 (que hemos cubierto antes) harán que todo este tema sea aún más poderoso.

Los temas del proyecto de polímero a través de propiedades personalizadas

Al menos lo hizo en los documentos v1. La idea es que tengas un componente web, como:

<iron-icon icon="[[toggleIcon]]">
</iron-icon>

Eso tenía valores predeterminados inteligentes, pero se creó específicamente para permitir el estilo a través de temas:

<style>
  iron-icon {
    fill: var(--icon-toggle-color, rgba(0,0,0,0));
    stroke: var(--icon-toggle-outline-color, currentcolor);
  }
  :host([pressed]) iron-icon {
    fill: var(--icon-toggle-pressed-color, currentcolor);
  }
</style>

Lo que significaba que podía establecer esas variables y hacer que el componente adoptara nuevos colores.

Soporte y retrocesos

El soporte ha mejorado bastante recientemente:

Estos datos de soporte del navegador son de Caniuse, que tiene más detalles. Un número indica que el navegador admite la función en esa versión y posteriores.

Escritorio

Cromo Firefox ES DECIR Borde Safari
49 31 No dieciséis 10

Móvil / Tableta

Android Chrome Android Firefox Androide Safari de iOS
96 94 96 10.0-10.2

Opera Mini e IE faltan notablemente. Ya cubrimos la idea de una reserva mediante la configuración de una propiedad no variable válida antes de la que usa una propiedad personalizada.

Como muchas funciones modernas de CSS, puede utilizar @supports para probar el soporte antes de usar:

@supports (--color: red) {
  :root {
    --color: red;
  }
  body {
    color: var(--color);
  }
}

Siempre depende de la situación, pero simplemente poner fallbacks en una declaración anterior es probablemente la forma más útil de lidiar con la falta de soporte en CSS. Tambien hay casos de borde.

Michael Scharnagl documenta un método JavaScript para realizar pruebas:

if (window.CSS && window.CSS.supports && window.CSS.supports('--a', 0)) {
  // CSS custom properties supported.
} else {
  // CSS custom properties not supported
}

Colores y accesibilidad

Al establecer colores para el texto y el color detrás de ese texto, el contraste entre esos colores es un problema de accesibilidad. Muy poco contraste, demasiado difícil de leer.

Una solución algo común a esto es elegir si el texto debe ser claro u oscuro (blanco o negro) según el color que se encuentra detrás.

David Halford tiene una demostración que calcula esto con JavaScript:

Y Brendan Saunders con Sass: