Hojas de estilo para construir

Estilos reutilizables sin inconvenientes.

Las hojas de estilo construibles son una forma de crear y distribuir diseños reutilizables cuando se usa Shadow DOM.

Navegadores compatibles

  • 73
  • 79
  • 101
  • 16.4

Origen

Siempre fue posible crear hojas de estilo con JavaScript. Sin embargo, históricamente, el proceso ha sido crear un elemento <style> con document.createElement('style') y, luego, acceder a su propiedad de hoja para obtener una referencia a la instancia subyacente CSSStyleSheet. Este método puede producir código CSS duplicado y su sobredimensionamiento, y el acto de adjuntar lleva a un destello de contenido sin estilo, ya sea que haya o no sobredimensionamiento. La interfaz CSSStyleSheet es la raíz de una colección de interfaces de representación CSS conocidas como CSSOM, que ofrece una manera programática de manipular hojas de estilo y eliminar los problemas asociados con el método anterior.

Diagrama en el que se muestra la preparación y aplicación de CSS.

Las hojas de estilo con las que se pueden construir permiten definir y preparar diseños de CSS compartidos y, luego, aplicar esos diseños a varias Shadow Roots o al documento de manera sencilla y sin duplicarlos. 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 la hoja se carga.

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

Creación de una hoja de estilo

En lugar de introducir una nueva API para lograr esto, la especificación Constructable StyleSheets permite crear hojas de estilo de manera imperativa invocando el constructor CSSStyleSheet(). El objeto CSSStyleSheet resultante tiene dos métodos nuevos que hacen que agregar y actualizar las reglas de la hoja de estilo sea más seguro y sin activar Flash of Unstyled Content (FOUC). Los métodos replace() y replaceSync() reemplazan la hoja de estilo por una cadena de CSS y replace() muestra una promesa. En ambos casos, las referencias de hojas de estilo externas no son compatibles: se ignoran las reglas @import y se genera 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..."

Cómo usar hojas de estilo construidas

La segunda función nueva que presentan las Hojas de estilo constructables es una propiedad adoptedStyleSheets disponible en Shadow Raíces y Documentos. Esto nos permite aplicar de forma explícita los estilos definidos por un CSSStyleSheet a un subárbol del DOM determinado. Para ello, configuramos la propiedad con un array de una o más hojas de estilo para aplicar 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);

Putting it all together

With Constructable StyleSheets, web developers now have an explicit solution for creating CSS StyleSheets and applying them to DOM trees. We have a new Promise-based API for loading StyleSheets from a string of CSS source that uses the browser's built-in parser and loading semantics. Finally, we have a mechanism for applying stylesheet updates to all usages of a StyleSheet, simplifying things like theme changes and color preferences.

View Demo

Looking ahead

The initial version of Constructable Stylesheets shipped with the API described here, but there's work underway to make things easier to use. There's a proposal to extend the adoptedStyleSheets FrozenArray with dedicated methods for inserting and removing stylesheets, which would obviate the need for array cloning and avoid potential duplicate stylesheet references.

More information