【问题标题】:Web components - Fonts and Material icons not working (@font-face)Web 组件 - 字体和材质图标不起作用 (@font-face)
【发布时间】:2020-05-13 13:28:48
【问题描述】:

我正在尝试通过运行以下命令使用 vue cli 3 创建 Web 组件

vue-cli-service build --target wc --name wc-demo 'src/App.vue'

我在网页组件中加载字体和材质图标时遇到问题。

我在 App.vue 的 style 标签内导入 roboto-font.scssma​​terial-icon.scss 这是创建的入口网络组件。

<style lang='scss'>
// @import url('https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap');
@import "~@/assets/fonts/roboto-font/roboto-font.scss";
@import "~@/assets/fonts/material-icons/material-icons.scss";
</style>

Material-icon.scss

$font-dir: "assets/fonts/material-icons/web-font/";

@font-face {
  font-family: 'Material Icons';
  font-style: normal;
  font-weight: 400;
  // src: url('https://fonts.gstatic.com/s/materialicons/v48/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2') format("woff2");

  src: url("#{$font-dir}flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2") format("woff2"),
  url("#{$font-dir}flUhRq6tzZclQEJ-Vdg-IuiaDsNa.woff") format("woff");
}

.material-icons {
  font-family: 'Material Icons';
  font-weight: normal;
  font-style: normal;
  display: inline-block;
  line-height: 1;
  text-transform: none;
  letter-spacing: normal;
  word-wrap: normal;
  white-space: nowrap;
  direction: ltr;
}

Roboto-font.scss

$font-dir: "assets/fonts/roboto-font/web-font/";

@font-face {
  font-family: 'Roboto';
  font-style: normal;
  font-weight: 100;
  src: url("#{$font-dir}KFOkCnqEu92Fr1MmgVxIIzQ.woff") format("woff");
}

使用

运行项目时一切正常

纱线发球

。字体在网络选项卡中加载正常,但在构建 Web 组件并使用“live server”将其加载到浏览器中后,字体不会在网络选项卡中加载。

让字体和图标工作的唯一方法是向 index.html 文件添加链接标签。但不在 web 组件内(在 shadow Dom 内)

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>wc-demo</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet"
    />
    <link
      href="https://fonts.googleapis.com/css?family=Roboto&display=swap"
      rel="stylesheet"
    />
    <title>Document</title>
  </head>
  <body>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src=“./wc-demo.js"></script>
    <wc-demo></wc-demo>
  </body>
</html>

谁能帮我理解如何在 web 组件中包含字体或在 html 文件头部分中使用它是唯一的选择吗?

我还链接了一些类似的问题,可能会帮助你帮助像我这样的人:-

https://bugs.chromium.org/p/chromium/issues/detail?id=336876

@font-face not working in polymer/web-components

https://robdodson.me/at-font-face-doesnt-work-in-shadow-dom/

Why doesn't Font Awesome work in my Shadow DOM?

【问题讨论】:

    标签: fonts font-face web-component


    【解决方案1】:

    我不确定这个问题是否仍然与作者相关,但是:

    我对这个话题做了相当多的研究,我发现:

    无法从 Web 组件内部导入字体。 Web 组件是自我隔离的。他们有自己的 DOM 树。这基本上意味着任何样式包含在父文档的head在网络组件中将不可用

    在 web 组件中使用自定义字体的唯一方法是:

    a) 禁用 shadow dom。然后,您可以在父文件(例如 head 标签)中获取字体并从 Web 组件内部使用这些字体。

    b) 包括字体定义:父组件和网络组件(代码重复)。

    更新

    经过一些实验,我似乎找到了解决方案。 在以下示例中,我使用了 StencilJS,它是专门用于 Web 组件开发的工具。

    使用 javascript / typescript 可以获取影子根元素的样式节点。 要访问此元素,我使用以下方法:

    @Element() private element: HTMLElement;

    来自 StencilJS 文档:

    @Element() 装饰器是如何访问类实例中的宿主元素的。这会返回一个 HTMLElement 的实例,因此可以在此处使用标准的 DOM 方法/事件。

    现在我可以访问样式节点并在那里设置(导入)前端。将字体导入作为常规字符串加入样式:

    this.element.shadowRoot.querySelector('style').innerText += "@import url('https://fonts.googleapis.com/css2?family=Almendra+Display&family=Open+Sans:wght@200&display=swap');";
    this.element.shadowRoot.querySelector('style').innerText += "p {font-family: 'Almendra Display', cursive;}";

    这是我用于使用 Stencil 构建的 Web 组件的解决方案。我坚信使用 React 也可以达到同样的效果。而且我认为它也可以在不使用任何框架的情况下完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-18
      • 1970-01-01
      • 2021-08-27
      • 1970-01-01
      • 1970-01-01
      • 2015-08-23
      • 1970-01-01
      • 2018-09-26
      相关资源
      最近更新 更多