可构造的样式表

样式无缝且可重复使用。

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

浏览器支持

  • 73
  • 79
  • 101
  • 16.4

来源

您始终可以使用 JavaScript 创建样式表。不过,一直以来,此流程都是使用 document.createElement('style') 创建 <style> 元素,然后访问其动作条属性以获取对底层 CSSStyleSheet 实例的引用。这种方法可能会产生重复的 CSS 代码,并导致出现膨胀,而且无论是否存在膨胀,附加样式都会导致一闪而过、样式化的内容。CSSStyleSheet 接口是一系列 CSS 表示形式接口(称为 CSSOM)的根,它提供了一种编程方法来操控样式表,并消除了与旧方法相关的问题。

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

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

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

构建样式表

通过使用可构造的样式表规范,您可以调用 CSSStyleSheet() 构造函数,以命令方式创建样式表,而无需引入新的 API 来实现这一点。生成的 CSSStyleSheet 对象有两个新方法,可让您更安全地添加和更新样式表规则,而无需触发未设置样式内容的 Flash (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 引入的第二个新功能是 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