可构造的样式表

无缝可重用样式。

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

Browser Support

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

Source

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

示意图:从编写 CSS 到实例化再到应用。

借助 Constructable Stylesheets,您可以定义和准备共享 CSS 样式,然后轻松地将这些样式应用于多个 Shadow Root 或 Document,而无需重复。对共享 CSSStyleSheet 的更新会应用于已采用该样式表的所有根,并且在加载样式表后,采用样式表的操作会快速同步进行。

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

构建样式表

Constructable StyleSheets 规范没有引入新的 API 来实现此目的,而是通过调用 CSSStyleSheet() 构造函数,以命令式方式创建样式表。生成的 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 Root 和 Document 上提供的 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);

综合应用

借助 Constructable StyleSheets,Web 开发者现在有了明确的解决方案来创建 CSS 样式表并将其应用于 DOM 树。我们推出了一个基于 Promise 的新 API,用于从使用浏览器内置解析器和加载语义的 CSS 源代码字符串加载样式表。最后,我们提供了一种机制,可将样式表更新应用于样式表的所有使用场景,从而简化主题更改和颜色偏好设置等操作。

观看演示

展望未来

Constructable Stylesheets 的初始版本随此处所述的 API 一起发布,但我们正在努力让其更易于使用。有一项提案,建议使用专用方法扩展 adoptedStyleSheets FrozenArray,以便插入和移除样式表,这样就无需克隆数组,并可避免潜在的重复样式表引用。

更多信息