为什么Font Awesome在我的Shadow DOM中不起作用?

时间:2019-02-06 02:56:40

标签: css google-chrome-extension font-awesome shadow-dom tailwind-css

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所示。

6 个答案:

答案 0 :(得分:3)

我与StencilJS有相同的问题。 经过数小时的奋斗和@Intervalia的回答,我得以解决它。

问题在于,当仅在阴影dom(您的自定义Web组件)中包含字体时,浏览器不会加载字体。这意味着这些字体也必须包含在普通的html文件(也就是浅色DOM)中,以便浏览器可以加载它们并在阴影dom中使用它们。

在我的情况下,我没有使用真棒字体,而是使用了自定义字体,但是我第二次尝试了真棒字体和干净的Stenciljs项目。无论您需要哪种自定义字体,解决方案始终相同。

步骤1:将字体移到您的项目中。我在“ src”文件夹中创建了一个单独的“ assets”文件夹,以便可以从所有组件进行访问。在此示例中,我下载了适用于Web环境https://fontawesome.com/download的字体。 (我不建议您使用“ npm install”,因为您也必须在index.html中使用它)

enter image description here

步骤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();
}