将样式导入Web组件

问题描述 投票:8回答:5

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

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

<template>
    <link rel="style" href="foo.css" />
    <h1>foo</h1>
</template>

我使用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
});
html5 web-component shadow-dom
5个回答
4
投票

现在直接在影子dom中支持<link>标签。

可以直接使用:

<link rel="stylesheet" href="yourcss1.css">
<link href="yourcss2.css" rel="stylesheet" type="text/css">  

它已被whatwg和W3C批准。

在阴影dom中使用css的有用链接:

直接css链接可用于阴影dom。


9
投票

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

<style> @import "../my/path/style.css"; </style>

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


4
投票

NB!

这个答案已经过时了

请通过下面的Himanshu Sharma检查答案

最新答案:https://stackoverflow.com/a/48202206/2035262

Polymer documentation说:

Polymer允许您在<polymer-element>定义中包含样式表,这是Shadow DOM本身不支持的功能。

这是一个有点奇怪的参考,但我不能直接google。看起来目前没有关于支持模板内部链接的传闻。

也就是说,无论你是否想要使用vanilla web组件,你都应该使用<style>标签内联你的css,或者在javascript中手动加载和应用你的css。


1
投票

可构造的样式表

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

有一个good writeup on the Google developers site,但我将在下面简要总结一下,底部有一个例子。

Creating a style sheet

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

const sheet = new CSSStyleSheet();

Setting and replacing the style:

可以通过调用方法replacereplaceSync来应用样式。

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

Applying the style to a document or shadow DOM

可以通过设置adoptedStyleSheets或shadow DOM的document属性来应用该样式。

document.adoptedStyleSheets = [sheet]

adoptedStyleSheets中的数组是冻结的,不能使用push()进行变异,但是您可以通过结合其现有值进行连接:

document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];

Inheriting from the document

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

// in the custom element class:
this.shadowRoot.adoptedStyleSheets = [...document.adoptedStyleSheets, myCustomSheet];

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

Example with Web Components

让我们创建一个名为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>

-2
投票

尝试<style>中的<template>元素:

<template>
    <style>
       h1 { 
         color: red;
         font-family: sans-serif;
       }
    </style>
    <h1>foo</h1>
</template>
© www.soinside.com 2019 - 2024. All rights reserved.