Font Awesome在我的影子DOM中不起作用,因为其中包含以下内容,以防止样式渗入和渗出:
:host {
all: initial; /* 1st rule so subsequent properties are reset. */
display: block;
contain: content; /* Boom. CSS containment FTW. */
}
我可以通过在:host
属性中内联其他样式表来使用其他样式表,但这不适用于Font Awesome,因为它在样式表中使用了相对路径。
我找到了this post,并在实现的范围内的CSS上进行了尝试,但是图标显示为正方形,如my example所示。
答案 0 :(得分:3)
我与StencilJS有相同的问题。 经过数小时的奋斗和@Intervalia的回答,我得以解决它。
问题在于,当仅在阴影dom(您的自定义Web组件)中包含字体时,浏览器不会加载字体。这意味着这些字体也必须包含在普通的html文件(也就是浅色DOM)中,以便浏览器可以加载它们并在阴影dom中使用它们。
在我的情况下,我没有使用真棒字体,而是使用了自定义字体,但是我第二次尝试了真棒字体和干净的Stenciljs项目。无论您需要哪种自定义字体,解决方案始终相同。
步骤1:将字体移到您的项目中。我在“ src”文件夹中创建了一个单独的“ assets”文件夹,以便可以从所有组件进行访问。在此示例中,我下载了适用于Web环境https://fontawesome.com/download的字体。 (我不建议您使用“ npm install”,因为您也必须在index.html中使用它)
步骤2:准备您的Web组件(在本例中为my-component.tsx)。您可以使用styleUrl s 属性导入多个CSS文件。只需从您的资产目录导入fontawesome CSS。
import { Component, Prop, h } from '@stencil/core';
@Component({
tag: 'my-component',
styleUrls: [
'my-component.css',
'../../assets/fontawesome/css/all.css'
],
shadow: true
})
export class MyComponent {
@Prop() first: string;
render() {
return <div> <i class="fas fa-question-circle"></i> </div>;
}
}
步骤3 ,在您要使用组件的位置准备文件(在本例中为index.html)。重要的一行是“链接”标签。这再次包括“真棒字体css”,并强制浏览器真正下载字体。
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<title>Stencil Component Starter</title>
<link rel="stylesheet" type="text/css" href="./assets/fontawesome/css/all.css">
</head>
<body>
<my-component first="Stencil" last="'Don't call me a framework' JS"></my-component>
</body>
</html>
我知道这感觉不对并且看起来很奇怪,但是仅在索引html或Web组件中包含很棒的字体是不够的。它必须确实包含在两个文件中。这并不意味着浏览器会多次加载它-只会加载一次。
这意味着您无法通过Web组件提供字体-据我所知。这不是stenciljs错误,这是浏览器的普遍问题。如果您有更好的解决方案,请告诉我。
这只是一个有趣的截图,它显示了浏览器仅包含在一个文件中时不会加载字体。 http://prntscr.com/p2f9tc
更新05.10.2019:
如果要在Web组件内使用字体,则上面的说明是正确的并且仍然是必要的。但是,您也可以在Web组件内部使用slot标签。比起您将字体从外部(HTML)自动绕到Web组件中。但是请注意,它仅适用于您在Web组件的标签之间编写的内容。
这意味着您可以使用<my-component> <i class="your-font"/> </my-component>
。在这种情况下,您不必将字体导入Web组件。
答案 1 :(得分:1)
如果不需要阴影:true,则可以直接通过index.html或主应用程序加载all.min.css。甚至可以加载all.min.js文件。
如果需要在影子dom内使用它,则需要将all.min.css加载到index.html中,还需要使用类似的方法将其加载到影子根目录中。
`
* def items = get response[*]
* def ids = $items[*].id
`
答案 2 :(得分:1)
我想分享我为将 Font Awesome 图标加载到模板组件(启用阴影)所做的工作...
在研究这个主题几个小时后,我想我已经找到了一种解决方案,它可以最有效地以不可知的方式捆绑我的组件,并且 HTML 标头中不包含任何其他样式表。
>我的解决方案是使用 stencil-inline-svg 模块,然后直接从 Font Awesome 模块导入 svg 文件,如下所示:
// the reference to the svg can be anything (searchIcon name).
// just make sure to import the correct svg from fontawesome node modules.
import searchIcon from 'fontawesome/svgs/regular/search.svg';
@Component({
tag: 'search-icon',
styleUrl: 'search-icon.scss',
shadow: true,
})
export class SearchIconComponent {
render(){
return (
{/* Not ideal to use innerHTML but this renders the full SVG markup */}
<span class="search-btn" innerHTML={searchIcon}></span>
)
}
}
不,我可以设置 css 规则来像这样修改图标的颜色和大小
.search-btn {
width: 40px; // Set SVG size at the parent.
svg path {
fill: #fff; // Update svg path color.
}
}
显然,这需要一点 Font Awesome 图标知识,以便您知道要导入哪些图标。
答案 3 :(得分:0)
我注意到的一件事是,如果页面未加载CSS文件,那么shadowDOM也将不会加载它。
我真的认为,唯一的问题是,如果未在页面上定义字体,则该字体将无法在组件中使用,因为其余的CSS似乎正确地适用于shadowDOM元素。
此示例仅显示了尝试加载CSS的shadowDOM,它不起作用:
let template = `
<style>
:host {
display: block;
}
</style>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<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>
`;
class MyEl extends HTMLElement {
connectedCallback() {
this.attachShadow({mode: 'open'}).innerHTML = template;
}
}
customElements.define("blog-header", MyEl);
<i class="fa fa-battery-full" style="font-size: 45px;"></i>
<hr/>
<blog-header></blog-header>
<hr/>
此示例显示了页面和加载它的shadowDOM并起作用:
let template = `
<style>
:host {
display: block;
}
</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>
`;
class MyEl extends HTMLElement {
connectedCallback() {
const styles = document.querySelector('link[href*="fontawesome"]');
this.attachShadow({mode: 'open'}).innerHTML = template;
if (styles) {
this.shadowRoot.appendChild(styles.cloneNode());
}
}
}
customElements.define("blog-header", MyEl);
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<i class="fa fa-battery-full" style="font-size: 45px;"></i>
<hr/>
<blog-header></blog-header>
<hr/>
我喜欢使用的代码在正文中寻找我想要的<link>
标签,然后在shadowDOM中使用该标签的副本。这样,我的组件不会不同步。 是的,如果组件不希望CSS发生变化,但是我发现它对我的项目效果很好,这可能会导致问题。
答案 4 :(得分:0)
Shadow Doms的样式受到限制。而且不会干扰外观
答案 5 :(得分:0)
FWIW我创建了一个帮助器方法,以在父页面级别创建超赞字体的链接。不知道这是否违反任何custom-elements
/ Web Components
标准,但我将继续在此处发布,希望我可以予以纠正:)它适用于我的用例(内部网络)现在申请。
export const addFontAwesomeStyles = () => {
injectStylesheet("https://use.fontawesome.com/releases/v5.13.0/css/all.css");
injectStylesheet("https://use.fontawesome.com/releases/v5.13.0/css/v4-shims.css");
}
export const injectStylesheet = (href: string) => {
const links = document.head.querySelectorAll("link");
// Already been injected
for(let l in links)
if(links[l].href == href) return;
const link = document.createElement('link');
link.rel = "stylesheet";
link.href = href;
document.head.appendChild(link)
}
然后在您的StencilJS组件的构造器中,可以像这样使用它:
//...
constructor() {
addFontAwesomeStyles();
}