【问题标题】:How to add fonts to create-react-app based projects?如何将字体添加到基于 create-react-app 的项目中?
【发布时间】:2017-05-31 06:31:23
【问题描述】:

我正在使用create-react-app,但不喜欢eject

不清楚通过@font-face 导入并在本地加载的字体应该放在哪里。

也就是说,我正在加载

@font-face {
  font-family: 'Myriad Pro Regular';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Regular'), url('MYRIADPRO-REGULAR.woff') format('woff');
}

有什么建议吗?

-- 编辑

包括丹在他的回答中提到的要点

➜  Client git:(feature/trivia-game-ui-2) ✗ ls -l public/static/fonts
total 1168
-rwxr-xr-x@ 1 maximveksler  staff  62676 Mar 17  2014 MYRIADPRO-BOLD.woff
-rwxr-xr-x@ 1 maximveksler  staff  61500 Mar 17  2014 MYRIADPRO-BOLDCOND.woff
-rwxr-xr-x@ 1 maximveksler  staff  66024 Mar 17  2014 MYRIADPRO-BOLDCONDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  66108 Mar 17  2014 MYRIADPRO-BOLDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  60044 Mar 17  2014 MYRIADPRO-COND.woff
-rwxr-xr-x@ 1 maximveksler  staff  64656 Mar 17  2014 MYRIADPRO-CONDIT.woff
-rwxr-xr-x@ 1 maximveksler  staff  61848 Mar 17  2014 MYRIADPRO-REGULAR.woff
-rwxr-xr-x@ 1 maximveksler  staff  62448 Mar 17  2014 MYRIADPRO-SEMIBOLD.woff
-rwxr-xr-x@ 1 maximveksler  staff  66232 Mar 17  2014 MYRIADPRO-SEMIBOLDIT.woff
➜  Client git:(feature/trivia-game-ui-2) ✗ cat src/containers/GameModule.css
.GameModule {
  padding: 15px;
}

@font-face {
  font-family: 'Myriad Pro Regular';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Regular'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-REGULAR.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Condensed';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Condensed'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-COND.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Semibold Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Semibold Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-SEMIBOLDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Semibold';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Semibold'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-SEMIBOLD.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Condensed Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Condensed Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-CONDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Condensed Italic';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Condensed Italic'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDCONDIT.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold Condensed';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold Condensed'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLDCOND.woff') format('woff');
}

@font-face {
  font-family: 'Myriad Pro Bold';
  font-style: normal;
  font-weight: normal;
  src: local('Myriad Pro Bold'), url('%PUBLIC_URL%/static/fonts/MYRIADPRO-BOLD.woff') format('woff');
}

【问题讨论】:

  • 您是否查看了用户指南中的“添加字体”部分?
  • @DanAbramov 我有,建议导入字体。但我觉得在实践中应该如何做还不清楚(至少对我来说不是)。与此同时,我已经完成了这个gist.github.com/maximveksler/5b4f80c5ded20237c3deebc82a31dcd5 并且它似乎可以工作(如果找不到字体文件,webpack 会发出警报)但我确信这不是最佳解决方案和一个示例或在此处记录它会帮助。联系我们!
  • 我回答了。你的方法在我看来是错误的:%PUBLIC_URL% 在 CSS 文件中不能工作(并且是不必要的)。此外,如指南中所述,您应该在几乎所有情况下都使用 JS 导入,而不是公用文件夹。
  • 是否有任何实用程序/程序包可以扫描指定文件夹中的字体并生成包含所有字体变体的脚本文件?手动写这些很乏味
  • 我来到这里实际上是为了能够“导入”字体,因为我使用的是 react-pdf 并且想要实际导入实际的字体文件,而不是 css。任何帮助表示赞赏。

标签: css reactjs fonts webpack create-react-app


【解决方案1】:

我加了

@font-face {
    font-family: 'Sanchez-Regular';
    src: local('Sanchez-Regular'),url(../assets/fonts/Sanchez/Sanchez-Regular.ttf) format('truetype');
}

而且效果非常好 稍后在 index.css 中使用它,就像我们使用所有其他字体一样

【讨论】:

    【解决方案2】:

    当为普通/斜体font-style 使用不同的字体文件时,您指定@font-face 的方式可能需要根据入口点而有所不同。 See my answer here:

    1. 如果您选择将css 文件直接链接到您的public/index.html,那么您通常可以使用font-face 与一个font-family 名称和不同的font-style
    @font-face {
      font-family: "FontName"; <---
      font-style: normal; <---
      font-weight: normal;
      src: url("path-to-assets/fonts/FontName.ttf") format("truetype");
    }
    @font-face {
      font-family: "FontName"; <---
      font-style: italic; <---
      font-weight: normal;
      src: url("path-to-assets/fonts/FontName-Italic.ttf") format("truetype");
    }
    
    /* Usage */
    .text {
      font-family: FontName;
      font-style: normal;
    }
    .text-italic {
      font-family: FontName;
      font-style: italic;
    }
    
    1. 如果您选择通过 Js 链接 css 文件进行捆绑,那么您需要为所有 italic 字体使用不同的 font-family 名称并使用 font-style 正常。
    @font-face {
      font-family: "FontName"; <---
      font-style: normal; <---
      font-weight: normal; /* normal | 300 | 400 | 600 | bold | etc */
      src: url("path-to-assets/fonts/FontName.ttf") format("truetype");
    }
    @font-face {
      font-family: "FontNameItalic";
      font-style: normal; <----
      font-weight: normal; /* normal | 300 | 400 | 600 | bold | etc */
      src: url("path-to-assets/fonts/FontName-Italic.ttf") format("truetype");
    }
    
    /* Usage */
    .text {
      font-family: FontName;
    }
    .text-italic {
      font-family: FontNameItalic;
    }
    

    【讨论】:

      【解决方案3】:

      有两种选择:

      使用导入

      这是建议的选项。它确保您的字体通过构建管道,在编译期间获取哈希值,以便浏览器缓存正常工作,并且如果文件丢失,您会收到编译错误。

      作为described in “Adding Images, Fonts, and Files”,你需要有一个从JS导入的CSS文件。比如默认src/index.js导入src/index.css

      import './index.css';
      

      这样的 CSS 文件会通过构建管道,并且可以引用字体和图像。例如,如果您将字体放在src/fonts/MyFont.woff 中,您的index.css 可能包含以下内容:

      @font-face {
        font-family: 'MyFont';
        src: local('MyFont'), url(./fonts/MyFont.woff) format('woff');
        /* other formats include: 'woff2', 'truetype, 'opentype',
                                  'embedded-opentype', and 'svg' */
      }
      

      注意我们如何使用以./ 开头的相对路径。这是帮助构建管道(由 Webpack 提供支持)发现此文件的特殊符号。

      通常这应该足够了。

      使用public 文件夹

      如果出于某种原因您希望使用构建管道,而是使用“经典方式”,您可以use the public folder 并将您的字体放在那里。

      这种方法的缺点是,在为生产环境进行编译时,文件不会得到哈希值,因此每次更改文件时都必须更新它们的名称,否则浏览器会缓存旧版本。

      如果您想这样做,请将字体放入public 文件夹的某个位置,例如,放入public/fonts/MyFont.woff。如果您采用这种方法,您也应该将 CSS 文件放入 public 文件夹中,并且不要从 JS 中导入它们,因为混合使用这些方法会非常混乱。所以,如果你仍然想这样做,你会有一个像public/index.css 这样的文件。您必须从 public/index.html 手动将 &lt;link&gt; 添加到此样式表:

      <link rel="stylesheet" href="%PUBLIC_URL%/index.css">
      

      在其中,您将使用常规的 CSS 表示法:

      @font-face {
        font-family: 'MyFont';
        src: local('MyFont'), url(fonts/MyFont.woff) format('woff');
      }
      

      注意我是如何使用fonts/MyFont.woff 作为路径的。这是因为index.css 位于public 文件夹中,因此它将从公共路径提供(通常是服务器根目录,但如果您部署到 GitHub Pages 并将homepage 字段设置为http://myuser.github.io/myproject,它将由/myproject提供服务)。但是fonts 也在public 文件夹中,因此它们将从fonts 相对提供(http://mywebsite.com/fontshttp://myuser.github.io/myproject/fonts)。因此我们使用相对路径。

      请注意,由于我们在此示例中避免使用构建管道,因此它不会验证文件是否确实存在。这就是我不推荐这种方法的原因。另一个问题是我们的index.css 文件没有被缩小并且没有得到哈希值。因此,最终用户的速度会变慢,而且浏览器可能会缓存文件的旧版本。

       使用哪种方式?

      使用第一种方法(“使用导入”)。我只描述了第二个,因为那是你试图做的(从你的评论来看),但它有很多问题,只有在你解决某些问题时才应该是最后的手段。

      【讨论】:

      • 文档中的示例很有用,我也有点困惑
      • 我发现我实际上必须使用 url ./fonts/Myfont.woff 而不是 ./Myfont.woff
      • 如果有人添加了ttf字体,你应该给truetype而不是ttf作为format*的参数。
      • 如果您使用的是otf,请在@milkersarac 之后输入opentype
      • 字体正在加载,但文件具有“.ttf”,并且由于 index.css 文件仍具有常规路径,因此未加载。有什么想法吗?
      【解决方案4】:

      您可以使用 Web API FontFace 构造函数(也可以是 Typescript)而不需要 CSS:

      export async function loadFont(fontFamily: string, url: string): Promise<void> {
          const font = new FontFace(fontFamily, `local(${fontFamily}), url(${url})`);
          // wait for font to be loaded
          await font.load();
          // add font to document
          document.fonts.add(font);
          // enable font with CSS class
          document.body.classList.add("fonts-loaded");
      }
      
      import ComicSans from "./assets/fonts/ComicSans.ttf";
      
      loadFont("Comic Sans ", ComicSans).catch((e) => {
          console.log(e);
      });
      

      Declare a file font.ts 与您的模块(仅限 TS):

      declare module "*.ttf";
      declare module "*.woff";
      declare module "*.woff2";
      

      如果 TS 无法找到 FontFace 类型作为其仍然正式的 WIP,请将 this declaration 添加到您的项目中。它可以在您的浏览器中运行,IE 除外。

      【讨论】:

        【解决方案5】:

        链接到你的 react js 的本地字体可能会失败。所以,我更喜欢使用 google 的在线 css 文件来链接字体。参考以下代码,

        <link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
        

        <style>
            @import url('https://fonts.googleapis.com/css?family=Roboto');
        </style>
        

        【讨论】:

          【解决方案6】:

          这里有一些方法:

          1。导入字体

          例如,对于使用 Roboto,安装包使用

          yarn add typeface-roboto
          

          npm install typeface-roboto --save
          

          在 index.js 中:

          import "typeface-roboto";
          

          许多开源字体和大多数 Google 字体都有 npm 包。您可以看到所有字体here。所有的包都来自那个project

          2。对于第三方托管的字体

          例如谷歌字体,你可以去fonts.google.com,在那里你可以找到你可以放在public/index.html中的链接

          会是这样的

          <link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet">
          

          <style>
              @import url('https://fonts.googleapis.com/css?family=Montserrat');
          </style>
          

          3。下载字体并将其添加到您的源代码中。

          下载字体。例如,对于谷歌字体,您可以转到fonts.google.com。点击下载按钮下载字体。

          将字体移动到src目录下的fonts目录

          src
          |
          `----fonts
          |      |
          |      `-Lato/Lato-Black.ttf
          |       -Lato/Lato-BlackItalic.ttf
          |       -Lato/Lato-Bold.ttf
          |       -Lato/Lato-BoldItalic.ttf
          |       -Lato/Lato-Italic.ttf
          |       -Lato/Lato-Light.ttf
          |       -Lato/Lato-LightItalic.ttf
          |       -Lato/Lato-Regular.ttf
          |       -Lato/Lato-Thin.ttf
          |       -Lato/Lato-ThinItalic.ttf
          |
          `----App.css
          

          现在,在App.css 中添加这个

          @font-face {
            font-family: 'Lato';
            src: local('Lato'), url(./fonts/Lato-Regular.otf) format('opentype');
          }
          
          @font-face {
              font-family: 'Lato';
              font-weight: 900;
              src: local('Lato'), url(./fonts/Lato-Bold.otf) format('opentype');
          }
          
          @font-face {
              font-family: 'Lato';
              font-weight: 900;
              src: local('Lato'), url(./fonts/Lato-Black.otf) format('opentype');
          }
          

          对于ttf 格式,你必须提到format('truetype')。对于woffformat('woff')

          现在你可以在类中使用字体了。

          .modal-title {
              font-family: Lato, Arial, serif;
              font-weight: black;
          }
          

          4。使用 web-font-loader 包

          使用安装包

          yarn add webfontloader
          

          npm install webfontloader --save
          

          src/index.js,你可以导入这个并指定需要的字体

          import WebFont from 'webfontloader';
          
          WebFont.load({
             google: {
               families: ['Titillium Web:300,400,700', 'sans-serif']
             }
          });
          

          【讨论】:

          • @sudobangbang 谢谢,解决方案#3 对我有用。但是-有没有办法不将fonts文件夹放在src下,而是放在public下?我试过了,但似乎不允许...
          • @YossiVainshtein,我不这么认为。当您使用 App.css 中的字体时,也应该使用它进行编译。
          • For ttf format, you have to mention format('truetype'). For woff, format('woff') 为我做了!谢谢!
          • 从源代码加载的网络字体是要走的路。如果您尝试从 Google 加载它们,您将被 Lighthouse 锁定,您将失去页面速度(更不用说中国用户了)。要提高 Web 字体的性能,请安装 woff2 cli 工具并使用其在 Google 字体 TTF 下载文件上的 woff2_compress 二进制文件来压缩它们以用于 Web。在您的 @font-face 规则中,使用 font-display rule 来加快速度。最后,您需要为 Web 发送 WOFF2 文件。
          • 字体已弃用,请使用字体源:github.com/fontsource/fontsource
          【解决方案7】:

          在遇到这个堆栈问题后,我花了整个上午来解决一个类似的问题。我在上面的答案中使用了 Dan 的第一个解决方案作为起点。

          问题

          我有一个开发环境(这是在我的本地机器上)、登台和生产环境。我的登台和生产环境位于同一台服务器上。

          该应用通过acmeserver/~staging/note-taking-app 部署到暂存版本,生产版本位于acmeserver/note-taking-app(责备 IT)。

          所有媒体文件(例如字体)在 dev 上都可以正常加载(即react-scripts start)。

          但是,当我创建并上传暂存和生产版本时,.css.js 文件加载正确,字体却没有加载。编译后的 .css 文件看起来路径正确,但浏览器 http 请求的路径非常错误(如下所示)。

          编译后的main.fc70b10f.chunk.css文件:

          @font-face {
            font-family: SairaStencilOne-Regular;
            src: url(note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf) ("truetype");
          }
          

          浏览器http请求如下图所示。请注意,当字体文件仅位于 /static/media/ 中以及复制目标文件夹时,它是如何添加到 /static/css/ 中的。我排除了服务器配置是罪魁祸首。

          Referer 也有部分问题。

          GET /~staging/note-taking-app/static/css/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf HTTP/1.1
          Host: acmeserver
          Origin: http://acmeserver
          Referer: http://acmeserver/~staging/note-taking-app/static/css/main.fc70b10f.chunk.css
          

          package.json 文件将homepage 属性设置为./note-taking-app。这是导致问题的原因。

          {
            "name": "note-taking-app",
            "version": "0.1.0",
            "private": true,
            "homepage": "./note-taking-app",
            "scripts": {
              "start": "env-cmd -e development react-scripts start",
              "build": "react-scripts build",
              "build:staging": "env-cmd -e staging npm run build",
              "build:production": "env-cmd -e production npm run build",
              "test": "react-scripts test",
              "eject": "react-scripts eject"
            }
            //...
          }
          

          解决方案

          这很啰嗦——但解决方案是:

          1. 根据环境更改PUBLIC_URL env 变量
          2. package.json 文件中删除homepage 属性

          下面是我的.env-cmdrc 文件。我使用.env-cmdrc 而不是常规的.env,因为它将所有内容放在一个文件中。

          {
            "development": {
              "PUBLIC_URL": "",
              "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
            },
            "staging": {
              "PUBLIC_URL": "/~staging/note-taking-app",
              "REACT_APP_API": "http://acmeserver/~staging/note-taking-app/api"
            },
            "production": {
              "PUBLIC_URL": "/note-taking-app",
              "REACT_APP_API": "http://acmeserver/note-taking-app/api"
            }
          }
          

          通过react-router-dom 路由也可以正常工作——只需使用PUBLIC_URL 环境变量作为basename 属性。

          import React from "react";
          import { BrowserRouter } from "react-router-dom";
          
          const createRouter = RootComponent => (
            <BrowserRouter basename={process.env.PUBLIC_URL}>
              <RootComponent />
            </BrowserRouter>
          );
          
          export { createRouter };
          

          服务器配置设置为将所有请求路由到./index.html 文件。

          最后,这是编译后的main.fc70b10f.chunk.css 文件在实施所讨论的更改后的样子。

          @font-face {
            font-family: SairaStencilOne-Regular;
            src: url(/~staging/note-taking-app/static/media/SairaStencilOne-Regular.ca2c4b9f.ttf)
              format("truetype");
          }
          

          阅读材料

          【讨论】:

            【解决方案8】:
            1. 转到谷歌字体https://fonts.google.com/
            2. 如下图所示选择您的字体:

            1. 复制该网址并将其粘贴到新选项卡中,您将获得用于添加该字体的 css 代码。在这种情况下,如果你去

            https://fonts.googleapis.com/css?family=Spicy+Rice

            它会这样打开:

            4,将代码复制并粘贴到您的 style.css 中,然后像这样开始使用该字体:

                  <Typography
                      variant="h1"
                      gutterBottom
                      style={{ fontFamily: "Spicy Rice", color: "pink" }}
                    >
                      React Rock
                    </Typography>
            

            结果:

            【讨论】:

            • 在许多情况下(例如:公司网络),访问外部 CDN 会被防火墙阻止,这种方法虽然正确,但可能不起作用。我们的组织中有多个 VLAN,除了 IT 和少数其他 VLAN 之外,所有 VLAN 都阻止外部 CDN 访问,这也意味着 Google 的内容 CDN 也被阻止。去过那里,做到了。
            【解决方案9】:

            我犯了这样的错误。

            @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i&amp;subset=cyrillic,cyrillic-ext,latin-ext";
            @import "https://use.fontawesome.com/releases/v5.3.1/css/all.css";
            

            这样可以正常工作

            @import url(https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i&amp;subset=cyrillic,cyrillic-ext,latin-ext);
            @import url(https://use.fontawesome.com/releases/v5.3.1/css/all.css);
            

            【讨论】:

              【解决方案10】:

              可以使用WebFont模块,大大简化了流程。

              render(){
                webfont.load({
                   custom: {
                     families: ['MyFont'],
                     urls: ['/fonts/MyFont.woff']
                   }
                });
                return (
                  <div style={your style} >
                    your text!
                  </div>
                );
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2021-06-02
                • 2019-02-16
                • 2021-02-13
                • 2018-11-27
                • 2017-10-09
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多