样式无缝且可重复使用。
可构建样式表是一种在使用阴影 DOM 时创建和分发可重复使用的样式的方法。
一直以来,您都可以使用 JavaScript 创建样式表。不过,该过程过去一直是使用 document.createElement('style')
创建 <style>
元素,然后访问其 sheet 属性以获取对底层 CSSStyleSheet 实例的引用。此方法可能会产生重复的 CSS 代码及其伴随的膨胀,并且无论是否存在膨胀,附加操作都会导致未设置样式的内容闪烁。CSSStyleSheet
接口是一系列 CSS 表示接口(称为 CSSOM)的根,可通过编程方式操控样式表,并消除与旧方法相关的问题。
借助可构建的样式表,您可以定义和准备共享的 CSS 样式,然后轻松地将这些样式应用于多个阴影根或文档,而不会出现重复。对共享 CSSStyleSheet 的更新将应用于已采用它的所有根,并且一旦加载了样式表,对样式表的采用就会变得快速而同步。
可构建样式表设置的关联非常适合许多不同的应用。它可用于提供集中式主题,供许多组件使用:主题可以是传递给组件的 CSSStyleSheet
实例,对主题的更新会自动传播到组件。它可用于将 CSS 自定义属性值分发到特定 DOM 子树,而无需依赖于级联。它甚至可以用作浏览器 CSS 解析器的直接接口,从而轻松预加载样式表,而无需将其注入 DOM。
构建样式表
可构造样式表规范允许通过调用 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..."
使用构造的样式表
可构建的样式表引入的第二项新功能是阴影根和文档上提供的 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);
综合应用
借助可构造的样式表,Web 开发者现在可以使用一个明确的解决方案来创建 CSS 样式表并将其应用于 DOM 树。我们推出了基于 Promise 的新 API,用于从 CSS 源字符串加载 StyleSheet,该 API 使用浏览器的内置解析器和加载语义。最后,我们提供了一种机制,用于将样式表更新应用于 StyleSheet 的所有用法,从而简化主题更改和颜色偏好设置等操作。
展望未来
可构建样式的初始版本随本文所述的 API 一起发布,但我们正在努力使其更易于使用。有一个提案,旨在通过用于插入和移除样式的专用方法扩展 adoptedStyleSheets
FrozenArray,从而无需进行数组克隆,并避免可能出现的重复样式表引用。