Hojas de estilo construibles

Estilos reutilizables sin problemas

Las hojas de estilo construibles son una forma de crear y distribuir estilos reutilizables cuando se usa el Shadow DOM.

Browser Support

  • Chrome: 73.
  • Edge: 79.
  • Firefox: 101.
  • Safari: 16.4.

Source

Siempre ha sido posible crear hojas de estilo con JavaScript. Sin embargo, históricamente, el proceso consistía en crear un elemento <style> con document.createElement('style') y, luego, acceder a su propiedad de hoja para obtener una referencia a la instancia CSSStyleSheet subyacente. Este método puede producir código CSS duplicado y su correspondiente aumento de tamaño, y el acto de adjuntar genera un destello de contenido sin diseño, independientemente de si hay un aumento de tamaño o no. La interfaz CSSStyleSheet es la raíz de una colección de interfaces de representación de CSS denominadas CSSOM, que ofrece una forma programática de manipular hojas de estilo y elimina los problemas asociados con el método anterior.

Diagrama que muestra el flujo desde el CSS creado hasta la creación de instancias y la aplicación.

Las hojas de estilo construibles permiten definir y preparar estilos CSS compartidos y, luego, aplicarlos a varias raíces de sombra o al documento con facilidad y sin duplicación. Las actualizaciones de una CSSStyleSheet compartida se aplican a todas las raíces en las que se adoptó, y la adopción de una hoja de estilo es rápida y síncrona una vez que se carga la hoja.

La asociación que establecen las hojas de estilo construibles se presta bien para una serie de aplicaciones diferentes. Se puede usar para proporcionar un tema centralizado que usen muchos componentes: el tema puede ser una instancia de CSSStyleSheet que se pasa a los componentes, y las actualizaciones del tema se propagan a los componentes automáticamente. Se puede usar para distribuir valores de propiedades personalizadas de CSS a subárboles del DOM específicos sin depender de la cascada. Incluso se puede usar como una interfaz directa para el analizador de CSS del navegador, lo que facilita la carga previa de hojas de estilo sin insertarlas en el DOM.

Cómo construir una hoja de estilo

En lugar de introducir una nueva API para lograr esto, la especificación de hojas de estilo construibles permite crear hojas de estilo de forma imperativa invocando el constructor CSSStyleSheet(). El objeto CSSStyleSheet resultante tiene dos métodos nuevos que hacen que sea más seguro agregar y actualizar reglas de hojas de estilo sin activar el destello de contenido sin estilo (FOUC). Los métodos replace() y replaceSync() reemplazan la hoja de estilo por una cadena de CSS, y replace() devuelve una promesa. En ambos casos, no se admiten las referencias a hojas de estilo externas; se ignoran las reglas @import y se produce una advertencia.

const sheet = new CSSStyleSheet();

// replace all styles synchronously:
sheet.replaceSync('a { color: red; }');

// replace all styles:
sheet.replace('a { color: blue; }')
  .then(() => {
    console.log('Styles replaced');
  })
  .catch(err => {
    console.error('Failed to replace styles:', err);
  });

// Any @import rules are ignored.
// Both of these still apply the a{} style:
sheet.replaceSync('@import url("styles.css"); a { color: red; }');
sheet.replace('@import url("styles.css"); a { color: red; }');
// Console warning: "@import rules are not allowed here..."

Usa hojas de estilo construidas

La segunda función nueva que presentan las hojas de estilo construibles es una propiedad adoptedStyleSheets disponible en Shadow Roots y Documents. Esto nos permite aplicar de forma explícita los estilos definidos por un CSSStyleSheet a un subárbol del DOM determinado. Para ello, establecemos la propiedad en un array de una o más hojas de estilo que se aplicarán a ese elemento.

// Create our shared stylesheet:
const sheet = new CSSStyleSheet();
sheet.replaceSync('a { color: red; }');

// Apply the stylesheet to a document:
document.adoptedStyleSheets.push(sheet);

// Apply the stylesheet to a Shadow Root:
const node = document.createElement('div');
const shadow = node.attachShadow({ mode: 'open' });
shadow.adoptedStyleSheets.push(sheet);

Revisión general

Con las hojas de estilo construibles, los desarrolladores web ahora tienen una solución explícita para crear hojas de estilo CSS y aplicarlas a los árboles del DOM. Tenemos una nueva API basada en promesas para cargar StyleSheets desde una cadena de fuente CSS que usa el analizador integrado del navegador y la semántica de carga. Por último, tenemos un mecanismo para aplicar actualizaciones de hojas de estilo a todos los usos de una StyleSheet, lo que simplifica aspectos como los cambios de tema y las preferencias de color.

Ver demostración

Con la mirada puesta en el futuro

La versión inicial de las hojas de estilo construibles se envió con la API que se describe aquí, pero se está trabajando para que sea más fácil de usar. Hay una propuesta para extender el FrozenArray adoptedStyleSheets con métodos dedicados para insertar y quitar hojas de estilo, lo que evitaría la necesidad de clonar arrays y evitaría posibles referencias duplicadas a hojas de estilo.

Más información