如何让导入的 css 字体/图标对影子 dom 中的元素产生影响

How to let imported css font / icons have effects on elements in the shadow dom?

本文关键字:dom 影子 元素 影响 图标 导入 css 字体      更新时间:2023-09-26

说我想使用影子dom创建自定义元素。模板中的某些元素具有在链接的 css 文件中指定的类名。现在我想让 css 规则对元素产生影响。但是由于阴影 dom 样式边界,我无法实现这一目标。

<link rel="stylesheet" type="text/css"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<template id="blog-header">
<header>
    <h1>DreamLine</h1>
    <nav>
        <ul>
            <li><a href="#0">Tour</a></li>
            <li><a href="#0">Blog</a></li>
            <li><a href="#0">Contact</a></li>
            <li><a href="#0">Error</a></li>
            <li><a href="#0"><i class="fa fa-search"></i>Search</a></li>
        </ul>
    </nav>
</header>
</template>
<script type="text/javascript">
var importDoc = document.currentScript.ownerDocument;
var proto = Object.create(HTMLElement.prototype, {
    createdCallback: {
        value: function () {
            var t = importDoc.querySelector("#blog-header");
            var clone = document.importNode(t.content, true);
            this.createShadowRoot().appendChild(clone);
        }
    }
});
document.registerElement("blog-header", {
    prototype: proto
});
</script>

你看,fa-search是一个在 font-awesome css 文件中定义的类,我该如何设置 <i> 元素的样式?

要在 Shadow DOM 中使用导入的字体(例如 FontAwesome),您应该:

1° 声明字体

首先,在主文档中包括<link rel="stylesheet">元素。它将声明一个@font-face CSS 规则,该规则将使字体可用于文档中的所有文本。

2° 导入样式表

然后,在 <template> 节点中使用 @import url CSS 规则导入相同的文件,以使 .fa-* 类选择器可从 Shadow DOM 中使用:

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<template id="blog-header">
  <style>
    @import url("https://use.fontawesome.com/releases/v5.7.1/css/all.css")
  </style>
  <header>
    <h1>DreamLine</h1>
    //...
  </header>
</template>

var importDoc = document.currentScript.ownerDocument;
var proto = Object.create(HTMLElement.prototype, {
	createdCallback: {
		value: function() {
			var t = importDoc.querySelector("#blog-header");
			var clone = document.importNode(t.content, true);
			this.createShadowRoot().appendChild(clone);
		}
	}
});
document.registerElement("blog-header", {prototype: proto});
/* 
@font-face {
    font-family: "FontAwesome";
    src: url("https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome-webfont.woff2?v=4.5.0") format('woff2');
  }
*/
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<template id="blog-header">
  <style>
    @import url("https://use.fontawesome.com/releases/v5.7.1/css/all.css")
  </style>
	<header>
		<h1>DreamLine</h1>
		<nav>
			<ul>
				<li><a href="#0">Tour</a></li>
				<li><a href="#0">Blog</a></li>
				<li><a href="#0">Contact</a></li>
				<li><a href="#0">Error</a></li>
				<li><a href="#0"><i class="fa fa-search"></i>Search</a></li>
			</ul>
		</nav>
	</header>
</template>
<blog-header></blog-header>

2019年更新

现在,您可以在影子 DOM 中使用<link rel="stylesheet">而不是@import url()

我导入了一个带有 mdi 图标的示例项目,作为子模块到一个更大的项目中。我的示例项目在传单地图中使用 mdi 图标,当地图图像在具有 dom-to-image 包的较大项目中下载时,这些图标未下载。我必须将其添加到 vue 文件中以使其工作的方式如下:

 <template>
  <div>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/MaterialDesign-Webfont/5.6.55/css/materialdesignicons.min.css" crossorigin="anonymous">