可构造样式表
这是一个允许构造CSSStyleSheet 对象的新功能。这些可以使用 JavaScript 从 css 文件设置或导入它们的内容,并应用于文档和 Web 组件的影子根。它将在 73 版的 Chrome 中可用,并且可能在不久的将来用于 Firefox。
有一个good writeup on the Google developers site,但我将在下面简要总结一下,底部有一个示例。
创建样式表
您通过调用构造函数创建一个新工作表:
const sheet = new CSSStyleSheet();
设置和替换样式:
可以通过调用replace或replaceSync方法来应用样式。
-
replaceSync 是同步的,不能使用任何外部资源:
sheet.replaceSync(`.redText { color: red }`);
-
replace 是 asynchronous 并且可以接受引用外部资源的 @import 语句。请注意,replace 返回需要相应处理的Promise。
sheet.replace('@import url("myStyle.css")')
.then(sheet => {
console.log('Styles loaded successfully');
})
.catch(err => {
console.error('Failed to load:', err);
});
将样式应用于文档或影子 DOM
可以通过设置document 或shadow DOM 的adoptedStyleSheets 属性来应用样式。
document.adoptedStyleSheets = [sheet]
adoptedStyleSheets 中的数组被冻结,不能与push() 发生突变,但可以通过与其现有值组合来连接:
document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
从文档继承
shadow DOM 可以以同样的方式从文档的adoptedStyleSheets 继承构造样式:
// in the custom element class:
this.shadowRoot.adoptedStyleSheets = [...document.adoptedStyleSheets, myCustomSheet];
请注意,如果它在构造函数中运行,则组件将仅继承在其创建之前采用的样式表。在connectedCallback 中设置adoptedStyleSheets 将为每个实例在连接时继承。值得注意的是,这不会导致FOUC。
Web 组件示例
让我们创建一个名为 x-card 的组件,它将文本包装在一个样式精美的 div 中。
// Create the component inside of an IIFE
(function() {
// template used for improved performance
const template = document.createElement('template');
template.innerHTML = `
<div id='card'></div>
`;
// create the stylesheet
const sheet = new CSSStyleSheet();
// set its contents by referencing a file
sheet.replace('@import url("xCardStyle.css")')
.then(sheet => {
console.log('Styles loaded successfully');
})
.catch(err => {
console.error('Failed to load:', err);
});
customElements.define('x-card', class extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: 'open'
});
// apply the HTML template to the shadow DOM
this.shadowRoot.appendChild(
template.content.cloneNode(true)
);
// apply the stylesheet to the shadow DOM
this.shadowRoot.adoptedStyleSheets = [sheet];
}
connectedCallback() {
const card = this.shadowRoot.getElementById('card');
card.textContent = this.textContent;
}
});
})();
<x-card>Example Text</x-card>
<x-card>More Text</x-card>