将样式导入Web组件

Ben*_*Ben 8 html5 web-component shadow-dom

将样式导入Web组件的规范方法是什么?

以下给出了一个错误HTML element <link> is ignored in shadow tree:

<template>
    <link rel="style" href="foo.css" />
    <h1>foo</h1>
</template>
Run Code Online (Sandbox Code Playgroud)

我使用以下方法使用shadow DOM插入它:

var importDoc, navBarProto;

importDoc = document.currentScript.ownerDocument;

navBarProto = Object.create(HTMLElement.prototype);
navBarProto.createdCallback = function() {
  var template, templateClone, shadow;

  template = importDoc.querySelector('template');
  templateClone = document.importNode(template.content, true);

  shadow = this.createShadowRoot();
  shadow.appendChild(templateClone);
};

document.registerElement('my-nav-bar', {
  prototype: navBarProto
});
Run Code Online (Sandbox Code Playgroud)

dex*_*cko 13

答案不再有效

@import语法已从CSSStyleSheet.replace()

可构造的样式表

这是一个允许构建CSSStyleSheet对象的新功能。这些可以使用 JavaScript 设置或从 css 文件导入其内容,并应用于文档和 Web 组件的影子根。它将在 Chrome 版本 73 中提供,并且可能在不久的将来在 Firefox 中提供。

Google 开发者网站上有一篇很好的文章,但我将在下面用底部的示例对其进行简要总结。

创建样式表

您可以通过调用构造函数来创建一个新工作表:

const sheet = new CSSStyleSheet();
Run Code Online (Sandbox Code Playgroud)

设置和替换样式:

replace可以通过调用方法或来应用样式replaceSync

  • replaceSync是同步的,不能使用任何外部资源:
    sheet.replaceSync(`.redText { color: red }`);
    
    Run Code Online (Sandbox Code Playgroud)
  • replace异步的,可以接受@import引用外部资源的语句。请注意,replace返回 aPromise需要进行相应处理。
    sheet.replace('@import url("myStyle.css")')
      .then(sheet => {
        console.log('Styles loaded successfully');
      })
      .catch(err => {
        console.error('Failed to load:', err);
      });
    
    Run Code Online (Sandbox Code Playgroud)

将样式应用到文档或影子 DOM

可以通过设置Shadow DOMadoptedStyleSheets的属性来应用样式。document

document.adoptedStyleSheets = [sheet]
Run Code Online (Sandbox Code Playgroud)

中的数组adoptedStyleSheets已冻结,无法使用 进行变异push(),但您可以通过与其现有值组合来连接:

document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
Run Code Online (Sandbox Code Playgroud)

从文档继承

adoptedStyleSheetsShadow DOM 可以以相同的方式从文档继承构造样式:

// in the custom element class:
this.shadowRoot.adoptedStyleSheets = [...document.adoptedStyleSheets, myCustomSheet];
Run Code Online (Sandbox Code Playgroud)

请注意,如果在构造函数中运行,则组件将仅继承在其创建之前采用的样式表。连接时每个实例都会继承adoptedStyleSheets该设置。connectedCallback值得注意的是,这不会导致FOUC

Web 组件示例

让我们创建一个名为 的组件x-card,它将文本包装在样式良好的div.

const sheet = new CSSStyleSheet();
Run Code Online (Sandbox Code Playgroud)
sheet.replaceSync(`.redText { color: red }`);
Run Code Online (Sandbox Code Playgroud)

  • 我在 caniuse.com 上没有看到任何关于此的跟踪。Firefox 对此有何支持?到目前为止,这看起来像是 Chrome 独有的技术,对吧? (2认同)

Jam*_*mer 9

如果您需要在<template>标签内放置外部样式,您可以尝试

<style> @import "../my/path/style.css"; </style>
Run Code Online (Sandbox Code Playgroud)

但我觉得这将在元素创建开始导入.


Him*_*rma 5

现在<link>,影子dom支持直接标记。

一个可以直接使用:

<link rel="stylesheet" href="yourcss1.css">
<link href="yourcss2.css" rel="stylesheet" type="text/css">  
Run Code Online (Sandbox Code Playgroud)

它已被whatwgW3C批准。

在Shadow dom中使用CSS的有用链接:

直接的CSS链接可以在影子dom中使用。

  • 当我从外部站点导入样式表时,这对我不起作用。这是禁止的吗?`&lt;link rel="stylesheet" href="https://some.site.com/style.css"/&gt;` (3认同)