可构造的样式表

样式支持无缝重复使用。

可构造的样式表是在使用 Shadow DOM 时创建和分发可重复使用的样式的方法。

浏览器支持

  • 73
  • 79
  • 101
  • 16.4

来源

一直以来,都可以使用 JavaScript 创建样式表。不过,历来都是使用 document.createElement('style') 创建 <style> 元素的过程,然后访问其工作表属性,获取对底层 CSSStyleSheet 实例的引用。这种方法可能会产生重复的 CSS 代码及其相应的膨胀,并且附加行为会导致一闪而过没有样式的内容(无论是否存在膨胀)。CSSStyleSheet 接口是 CSS 表示法接口集合(称为 CSSOM)的根,提供了一种编程方式来操控样式表,同时消除了与旧方法相关的问题。

展示 CSS 准备和应用的示意图。

借助可构造的样式表,您可以定义和准备共享 CSS 样式,然后将这些样式轻松应用于多个阴影根或文档,而不会出现重复内容。对共享 CSSStyleSheet 的更新将应用于已采用它的所有根,并且一旦加载了样式表,对样式表的采用就会变得快速、同步。

由 Constructable 样式表设置的关联适用于许多不同的应用。它可用于提供集中式主题,供许多组件使用:主题可以是传递给组件的 CSSStyleSheet 实例,对主题的更新会自动传播到组件。它可用于将 CSS 自定义属性值分布到特定的 DOM 子树,而无需依赖级联。它甚至可以用作浏览器 CSS 解析器的直接接口,让您可以轻松预加载样式表,而无需将其注入 DOM。

构建样式表

Constructable StyleSheets 规范可让您通过调用 CSSStyleSheet() 构造函数以命令方式创建样式表,而不是引入新的 API 来实现这一点。生成的 CSSStyleSheet 对象有两种新方法,可让您更安全地添加和更新样式表规则,而不会触发刷写无样式内容 (FOUC)。replace()replaceSync() 方法都会将样式表替换为 CSS 字符串,并且 replace() 会返回 Promise。这两种情况下均不支持外部样式表引用 - 所有 @import 规则都会被忽略并生成警告。

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..."

使用构造的样式表

Constructable StyleSheets 引入的第二项新功能是 Shadow RootDocuments 上提供的 adoptedStyleSheets 属性。这样,我们就可以将 CSSStyleSheet 定义的样式明确应用于给定的 DOM 子树。为此,我们将该属性设置为一个数组,其中包含一个或多个要应用于该元素的样式表。

// 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